diff --git a/cli/buildengine.ts b/cli/buildengine.ts index 2f82456e7271..95ee1d5e0d6e 100644 --- a/cli/buildengine.ts +++ b/cli/buildengine.ts @@ -411,7 +411,7 @@ function updateCodalBuildAsync() { .then( () => /v\d+/.test(cs.gittag) ? Promise.resolve() : codalGitAsync("pull"), e => - codalGitAsync("checkout", "master") + codalGitAsync("checkout", "master") // leave as master .then(() => codalGitAsync("pull"))) .then(() => codalGitAsync("checkout", cs.gittag)) } diff --git a/cli/cli.ts b/cli/cli.ts index 20fce52b0bc5..8eb0c570d6d3 100644 --- a/cli/cli.ts +++ b/cli/cli.ts @@ -251,49 +251,6 @@ function searchAsync(...query: string[]) { }) } -function pkginfoAsync(repopath: string) { - let parsed = pxt.github.parseRepoId(repopath) - if (!parsed) { - console.log('Unknown repo'); - return Promise.resolve(); - } - - const pkgInfo = (cfg: pxt.PackageConfig, tag?: string) => { - pxt.log(`name: ${cfg.name}`) - pxt.log(`description: ${cfg.description}`) - if (pxt.appTarget.appTheme) - pxt.log(`shareable url: ${pxt.appTarget.appTheme.embedUrl}#pub:gh/${parsed.fullName}${tag ? "#" + tag : ""}`) - } - - return pxt.packagesConfigAsync() - .then(config => { - const status = pxt.github.repoStatus(parsed, config); - pxt.log(`github org: ${parsed.owner}`); - if (parsed.tag) pxt.log(`github tag: ${parsed.tag}`); - pxt.log(`package status: ${status == pxt.github.GitRepoStatus.Approved ? "approved" : status == pxt.github.GitRepoStatus.Banned ? "banned" : "neutral"}`) - if (parsed.tag) - return pxt.github.downloadPackageAsync(repopath, config) - .then(pkg => { - let cfg: pxt.PackageConfig = JSON.parse(pkg.files[pxt.CONFIG_NAME]) - pkgInfo(cfg, parsed.tag) - pxt.debug(`size: ${JSON.stringify(pkg.files).length}`) - }) - - return pxt.github.pkgConfigAsync(parsed.fullName) - .then(cfg => { - pkgInfo(cfg) - return pxt.github.listRefsAsync(repopath) - .then(tags => { - pxt.log("tags: " + tags.join(", ")) - return pxt.github.listRefsAsync(repopath, "heads") - }) - .then(heads => { - pxt.log("branches: " + heads.join(", ")) - }) - }) - }) -} - export function pokeRepoAsync(parsed: commandParser.ParsedCommand): Promise { const repo = parsed.args[0]; @@ -450,18 +407,18 @@ function ciAsync() { fs.writeFileSync(npmrc, cfg) } - const latest = branch == "master" ? "latest" : "git-" + branch - // upload locs on build on master - const masterOrReleaseBranchRx = /^(master|v\d+\.\d+\.\d+)$/; - const apiStringBranchRx = pxt.appTarget.uploadApiStringsBranchRx - ? new RegExp(pxt.appTarget.uploadApiStringsBranchRx) - : masterOrReleaseBranchRx; + const defaultBranch = pxt.github.isDefaultBranch(branch) + const latest = defaultBranch ? "latest" : "git-" + branch + // upload locs on build on default or releases + const apiStringBranchRx: (t: string) => boolean = ((t:string) => new RegExp(pxt.appTarget.uploadApiStringsBranchRx).test(t)) + ? ((t: string) => new RegExp(pxt.appTarget.uploadApiStringsBranchRx).test(t)) + : ((t: string) => pxt.github.isDefaultOrReleaseBranch(t)); const uploadDocs = !pullRequest && !!pxt.appTarget.uploadDocs - && masterOrReleaseBranchRx.test(branch); + && pxt.github.isDefaultOrReleaseBranch(branch); const uploadApiStrings = !pullRequest && (!!pxt.appTarget.uploadDocs || pxt.appTarget.uploadApiStringsBranchRx) - && apiStringBranchRx.test(branch); + && apiStringBranchRx(branch); pxt.log(`tag: ${tag}`); pxt.log(`branch: ${branch}`); @@ -482,7 +439,7 @@ function ciAsync() { .then(isTaggedCommit => { pxt.log(`is tagged commit: ${isTaggedCommit}`); let p = npmPublishAsync(); - if (branch === "master" && isTaggedCommit) { + if (defaultBranch && isTaggedCommit) { if (uploadDocs) p = p .then(() => buildWebStringsAsync()) @@ -1664,14 +1621,14 @@ function ciBuildInfo(): CiBuildInfo { pxt.log(`event name: ${eventName}`); - // PR: not on master or not a release number + // PR: not on default or not a release number return { ci: "githubactions", branch, tag, commit, commitUrl: "https://github.com/" + repoSlug + "/commits/" + commit, - pullRequest: !(branch == "master" || /^v\d+\.\d+\.\d+$/.test(tag)) + pullRequest: !pxt.github.isDefaultOrReleaseBranch(branch) } } } @@ -5429,32 +5386,6 @@ function writeProjects(prjs: SavedProject[], outDir: string): string[] { return dirs; } -function cherryPickAsync(parsed: commandParser.ParsedCommand) { - const commit = parsed.args[0]; - const name = parsed.flags["name"] || commit.slice(0, 7); - let majorVersion = parseInt(pxtVersion().split('.')[0]); - const gitAsync = (args: string[]) => nodeutil.spawnAsync({ - cmd: "git", - args - }) - - let branches: string[] = []; - for (let i = majorVersion - 1; i >= 0; --i) branches.push("v" + i); - pxt.log(`cherry picking ${commit} into ${branches.join(', ')}`) - - let p = gitAsync(["pull"]); - branches.forEach(branch => { - const pr = `cp/${branch}${name}`; - p = p.then(() => gitAsync(["checkout", branch])) - .then(() => gitAsync(["pull"])) - .then(() => gitAsync(["checkout", "-b", pr])) - .then(() => gitAsync(["cherry-pick", commit])) - .then(() => gitAsync(["push", "--set-upstream", "origin", pr])); - }) - - return p.catch(() => gitAsync(["checkout", "master"])); -} - function checkDocsAsync(parsed?: commandParser.ParsedCommand): Promise { return internalCheckDocsAsync( true, @@ -6156,7 +6087,6 @@ function testGithubPackagesAsync(parsed: commandParser.ParsedCommand): Promise pyconv.convertAsync(c.args, !!c.flags["internal"])) - p.defineCommand({ - name: "cherrypick", - aliases: ["cp"], - help: "recursively cherrypicks and push branches", - argString: "", - advanced: true, - flags: { - "name": { - description: "name of the branch", - type: "string", - argument: "name" - } - } - }, cherryPickAsync); - p.defineCommand({ name: "decompile", help: "decompile typescript files", diff --git a/docs/github-explorer.html b/docs/github-explorer.html index d7429f5610bd..005dac37d9c3 100644 --- a/docs/github-explorer.html +++ b/docs/github-explorer.html @@ -138,7 +138,7 @@ login } nameWithOwner - object(expression: "master:pxt.json") { + object(expression: "HEAD:pxt.json") { ... on Blob { text } @@ -251,7 +251,7 @@ const url = targets[repo.target].url + `?nocookiebanner=1&${readOnly ? 'controller=1&readonly=1&ws=mem&' : 'editorLayout=ide&nosandbox=1'}#pub:github:` - + repo.nameWithOwner + "#master"; + + repo.nameWithOwner; $("#makecodecolumn").attr("src", url); }); diff --git a/localtypings/pxtarget.d.ts b/localtypings/pxtarget.d.ts index 456e7a9d9693..c6177501cbdc 100644 --- a/localtypings/pxtarget.d.ts +++ b/localtypings/pxtarget.d.ts @@ -77,7 +77,7 @@ declare namespace pxt { compileService?: TargetCompileService; ignoreDocsErrors?: boolean; uploadApiStringsBranchRx?: string; // regular expression to match branches that should upload api strings - uploadDocs?: boolean; // enable uploading to crowdin on master or v* builds + uploadDocs?: boolean; // enable uploading to crowdin on default branch or v* builds variants?: Map; // patches on top of the current AppTarget for different chip variants multiVariants?: string[]; alwaysMultiVariant?: boolean; @@ -244,7 +244,7 @@ declare namespace pxt { codalTarget?: string | { name: string; // "codal-arduino-uno" url: string; // "https://github.com/lancaster-university/codal-arduino-uno" - branch: string; // "master" + branch: string; // "main" type: string; // "git" branches?: pxt.Map; // overrides repo url -> commit sha }; diff --git a/pxtlib/browserutils.ts b/pxtlib/browserutils.ts index 3afbbdc1aea0..b617f18ef4c5 100644 --- a/pxtlib/browserutils.ts +++ b/pxtlib/browserutils.ts @@ -755,7 +755,7 @@ namespace pxt.BrowserUtils { class MemTranslationDb implements ITranslationDb { translations: pxt.Map = {}; key(lang: string, filename: string, branch: string) { - return `${lang}|${filename}|${branch || "master"}`; + return `${lang}|${filename}|${branch || "default"}`; } get(lang: string, filename: string, branch: string): ITranslationDbEntry { return this.translations[this.key(lang, filename, branch)]; @@ -1030,6 +1030,7 @@ namespace pxt.BrowserUtils { } function getTutorialInfoKey(filename: string, branch?: string) { + // TODO: 'main' support return `${filename}|${branch || "master"}`; } diff --git a/pxtlib/cpp.ts b/pxtlib/cpp.ts index 6e856312d6a5..49b84408ff69 100644 --- a/pxtlib/cpp.ts +++ b/pxtlib/cpp.ts @@ -1016,7 +1016,7 @@ namespace pxt.cpp { "libraries": U.values(codalLibraries).map(r => ({ "name": r.project, "url": "https://github.com/" + r.fullName, - "branch": r.tag || "master", + "branch": r.tag || "master", // leave as master "type": "git" })) } diff --git a/pxtlib/docsrender.ts b/pxtlib/docsrender.ts index 0a1d18725b4d..99b4b3ce52ce 100644 --- a/pxtlib/docsrender.ts +++ b/pxtlib/docsrender.ts @@ -535,7 +535,7 @@ namespace pxt.docs { if (opts.repo) markdown += ` \`\`\`package -${opts.repo.name.replace(/^pxt-/, '')}=github:${opts.repo.fullName}#${opts.repo.tag || "master"} +${opts.repo.name.replace(/^pxt-/, '')}=github:${opts.repo.fullName}${opts.repo.tag ? `#${opts.repo.tag}` : ""} \`\`\` `; diff --git a/pxtlib/github.ts b/pxtlib/github.ts index b9f769325879..083460e5e88e 100644 --- a/pxtlib/github.ts +++ b/pxtlib/github.ts @@ -166,19 +166,25 @@ namespace pxt.github { private configs: pxt.Map = {}; private packages: pxt.Map = {}; - private proxyWithCdnLoadPackageAsync(repopath: string, tag: string): Promise { + private async proxyWithCdnLoadPackageAsync(repopath: string, tag: string): Promise { // cache lookup - const key = `${repopath}/${tag}`; + const key = `${repopath}/${tag || "default"}`; let res = this.packages[key]; if (res) { - pxt.debug(`github cache ${repopath}/${tag}/text`); + pxt.debug(`github cache ${repopath}/${tag || "default"}/text`); return Promise.resolve(res); } // load and cache const parsed = parseRepoId(repopath) - return ghProxyWithCdnJsonAsync(join(parsed.slug, tag, parsed.fileName, "text")) - .then(v => this.packages[key] = { files: v }); + if (!tag || tag === "default") { + // resolve master vs main + const repo: { defaultBranch: string } = await ghProxyWithCdnJsonAsync(parsed.slug) + tag = repo.defaultBranch + } + const v = await ghProxyWithCdnJsonAsync(join(parsed.slug, tag, parsed.fileName, "text")) + const r = this.packages[key] = { files: v } + return r; } private cacheConfig(key: string, v: string) { @@ -188,8 +194,7 @@ namespace pxt.github { } async loadConfigAsync(repopath: string, tag: string): Promise { - if (!tag) tag = "master"; - + U.assert(!!tag) // cache lookup const key = `${repopath}/${tag}`; let res = this.configs[key]; @@ -214,7 +219,7 @@ namespace pxt.github { } async loadPackageAsync(repopath: string, tag: string): Promise { - if (!tag) tag = "master"; + U.assert(!!tag) // try using github proxy first if (hasProxy()) { @@ -384,7 +389,7 @@ namespace pxt.github { return (resp.statusCode == 200) } - export async function putFileAsync(repopath: string, path: string, content: string) { + export async function putFileAsync(repopath: string, branch: string, path: string, content: string) { const parsed = parseRepoId(repopath); await ghRequestAsync({ url: `https://api.github.com/repos/${pxt.github.join(parsed.slug, "contents", parsed.fileName, path)}`, @@ -393,7 +398,7 @@ namespace pxt.github { data: { message: lf("Initialize empty repo"), content: btoa(U.toUTF8(content)), - branch: "master" + branch }, successCodes: [201] }) @@ -451,7 +456,7 @@ namespace pxt.github { } export function getRefAsync(repopath: string, branch: string) { - branch = branch || "master"; + U.assert(!!branch) return ghGetJsonAsync("https://api.github.com/repos/" + repopath + "/git/refs/heads/" + branch) .then(resolveRefAsync) .catch(err => { @@ -563,7 +568,8 @@ namespace pxt.github { .then(resolveRefAsync)) } - export function pkgConfigAsync(repopath: string, tag = "master") { + export function pkgConfigAsync(repopath: string, tag: string) { + U.assert(!!tag) return db.loadConfigAsync(repopath, tag) } @@ -662,7 +668,7 @@ namespace pxt.github { forks: number; open_issues: number; watchers: number; - default_branch: string; // "master", + default_branch: string; score: number; // 6.7371006 // non-github, added to track search request @@ -701,6 +707,16 @@ namespace pxt.github { fork?: boolean; } + export function isDefaultBranch(branch: string, repo?: GitRepo) { + if (repo && repo.defaultBranch) + return branch === repo.defaultBranch; + return /^(main|master)$/.test(branch); + } + + export function isDefaultOrReleaseBranch(branch: string, repo?: GitRepo) { + return isDefaultBranch(branch) || /^v\d+\.\d+\.\d+$/.test(branch); + } + export function listUserReposAsync(): Promise { const q = `{ viewer { @@ -765,7 +781,7 @@ namespace pxt.github { }).then(v => mkRepo(v)) } - export async function enablePagesAsync(repo: string) { + export async function enablePagesAsync(repo: string, branch: string) { // https://developer.github.com/v3/repos/pages/#enable-a-pages-site // try read status const parsed = parseRepoId(repo); @@ -782,7 +798,7 @@ namespace pxt.github { try { const r = await ghPostAsync(`https://api.github.com/repos/${parsed.slug}/pages`, { source: { - branch: "master", + branch, path: "/" } }, { @@ -911,7 +927,12 @@ namespace pxt.github { } // try github apis const r = await ghGetJsonAsync("https://api.github.com/repos/" + rid.slug) - return mkRepo(r, { config, fullName: rid.fullName, fileName: rid.fileName, tag: rid.tag }); + return mkRepo(r, { + config, + fullName: rid.fullName, + fileName: rid.fileName, + tag: rid.tag, + }); } function proxyRepoAsync(rid: ParsedRepo, status: GitRepoStatus): Promise { @@ -927,7 +948,7 @@ namespace pxt.github { slug: rid.slug, name: rid.fileName ? `${meta.name}-${rid.fileName}` : meta.name, description: meta.description, - defaultBranch: meta.defaultBranch || "master", + defaultBranch: meta.defaultBranch, tag: rid.tag, status }; @@ -1012,13 +1033,14 @@ namespace pxt.github { } export function stringifyRepo(p: ParsedRepo) { - return p ? "github:" + p.fullName.toLowerCase() + "#" + (p.tag || "master") : undefined; + return p ? "github:" + p.fullName.toLowerCase() + "#" + (p.tag || "default") : undefined; } export function normalizeRepoId(id: string) { const gid = parseRepoId(id); if (!gid) return undefined; - gid.tag = gid.tag || "master"; + // this does not work anymore + gid.tag = gid.tag; return stringifyRepo(gid); } diff --git a/webapp/src/data.ts b/webapp/src/data.ts index 1b06db8afac6..c04efddc2327 100644 --- a/webapp/src/data.ts +++ b/webapp/src/data.ts @@ -64,12 +64,14 @@ mountVirtualApi("gh-search", { isOffline: () => !Cloud.isOnline(), }) +/* does not seem to be used mountVirtualApi("gh-pkgcfg", { getAsync: query => - pxt.github.pkgConfigAsync(stripProtocol(query)).catch(core.handleNetworkError), + pxt.github.pkgConfigAsync(stripProtocol(query), ).catch(core.handleNetworkError), expirationTime: p => 60 * 1000, isOffline: () => !Cloud.isOnline(), }) +*/ // gh-commits:repo#sha mountVirtualApi("gh-commits", { @@ -95,7 +97,8 @@ mountVirtualApi("target-config", { pxt.storage.setLocal("targetconfig", JSON.stringify(js)) invalidate("target-config"); invalidate("gh-search"); - invalidate("gh-pkgcfg"); + // does not seem to be used + // invalidate("gh-pkgcfg"); } return js; }) diff --git a/webapp/src/db.ts b/webapp/src/db.ts index 120c793d5809..cb73ad948666 100644 --- a/webapp/src/db.ts +++ b/webapp/src/db.ts @@ -96,8 +96,9 @@ class GithubDb implements pxt.github.IGithubDb { private table = new Table("github"); loadConfigAsync(repopath: string, tag: string): Promise { + pxt.U.assert(!!tag) // don't cache master - if (tag == "master") + if (pxt.github.isDefaultBranch(tag)) return this.mem.loadConfigAsync(repopath, tag); const id = `config-${repopath}-${tag}`; @@ -119,9 +120,9 @@ class GithubDb implements pxt.github.IGithubDb { ); } loadPackageAsync(repopath: string, tag: string): Promise { - tag = tag || "master"; + pxt.U.assert(!!tag) // don't cache master - if (tag == "master") + if (pxt.github.isDefaultBranch(tag)) return this.mem.loadPackageAsync(repopath, tag); const id = `pkg-${repopath}-${tag}`; diff --git a/webapp/src/dialogs.tsx b/webapp/src/dialogs.tsx index e236420a9de7..77dc6f6e6517 100644 --- a/webapp/src/dialogs.tsx +++ b/webapp/src/dialogs.tsx @@ -81,7 +81,7 @@ function renderCompileLink(variantName: string, cs: pxt.TargetCompileService) { if (typeof cs.codalTarget === "object" && typeof cs.codalTarget.url === "string") { url = cs.codalTarget.branch ? pxt.BrowserUtils.joinURLs(cs.codalTarget.url, "releases/tag", cs.codalTarget.branch) : cs.codalTarget.url; - version = cs.codalTarget.branch || "master"; + version = cs.codalTarget.branch || "master"; // leave as "master" name = cs.codalTarget.name || cs.serviceId; } else { diff --git a/webapp/src/githubbutton.tsx b/webapp/src/githubbutton.tsx index a01faf9b878c..7a9d6f147202 100644 --- a/webapp/src/githubbutton.tsx +++ b/webapp/src/githubbutton.tsx @@ -63,10 +63,10 @@ export class GithubButton extends sui.UIElement maxLength) displayName = displayName.slice(0, maxLength - 2) + '..'; @@ -84,11 +84,10 @@ export class GithubButton extends sui.UIElement {displayName} - + ; } } diff --git a/webapp/src/gitjson.tsx b/webapp/src/gitjson.tsx index 3ba367bc1f7d..68daf0af9f14 100644 --- a/webapp/src/gitjson.tsx +++ b/webapp/src/gitjson.tsx @@ -165,10 +165,17 @@ class GithubComponent extends data.Component { await f.setContentAsync(JSON.stringify(gs, null, 4)) } - private async switchProjectToBranchAsync(newBranch: string) { + private async switchProjectToBranchAsync(newBranch?: string) { const { header } = this.props.parent.state; const gs = this.getGitJson(); const parsed = this.parsedRepoId() + + if (!newBranch) { + const packagesConfig = await pxt.packagesConfigAsync() + const repo = await pxt.github.repoAsync(parsed.slug, packagesConfig) + newBranch = repo.defaultBranch + } + header.githubId = parsed.fullName + "#" + newBranch gs.repo = header.githubId await this.saveGitJsonAsync(gs) @@ -208,7 +215,7 @@ class GithubComponent extends data.Component { } } - public async switchBranchAsync(branch: string) { + public async switchBranchAsync(branch?: string) { await this.setStateAsync({ needsCommitMessage: false }); const prevBranch = this.parsedRepoId().tag try { @@ -234,7 +241,7 @@ class GithubComponent extends data.Component { })) // only branch from master... - if (gid.tag == "master") { + if (pxt.github.isDefaultBranch(gid.tag)) { branchList.unshift({ name: lf("Create new branch"), description: lf("Based on {0}", gid.tag), @@ -693,7 +700,9 @@ class GithubComponent extends data.Component { ` */ - const id = await pxt.github.createPRFromBranchAsync(gh.slug, "master", gh.tag, title, msg); + const packagesConfig = await pxt.packagesConfigAsync() + const repo = await pxt.github.repoAsync(gh.slug, packagesConfig) + const id = await pxt.github.createPRFromBranchAsync(gh.slug, repo.defaultBranch, gh.tag, title, msg); data.invalidateHeader("pkg-git-pr", this.props.parent.state.header); core.infoNotification(lf("Pull request created successfully!", id)); } catch (e) { @@ -749,15 +758,15 @@ class GithubComponent extends data.Component { const hasissue = pullStatus == workspace.PullStatus.BranchNotFound || pullStatus == workspace.PullStatus.NoSourceControl; const haspull = pullStatus == workspace.PullStatus.GotChanges; const githubId = this.parsedRepoId() - const master = githubId.tag == "master"; + const isDefaultBranch = pxt.github.isDefaultBranch(githubId.tag); const user = this.getData("github:user") as pxt.editor.UserInfo; // don't use gs.prUrl, as it gets cleared often - const url = `https://github.com/${githubId.slug}/${master && !githubId.fileName ? "" : pxt.github.join("tree", githubId.tag || "master", githubId.fileName)}`; + const url = `https://github.com/${githubId.slug}}`; const needsToken = !pxt.github.token; // this will show existing PR if any const pr: pxt.github.PullRequest = this.getData("pkg-git-pr:" + header.id) - const showPr = pr !== null && (gs.isFork || !master); + const showPr = pr !== null && (gs.isFork || !isDefaultBranch); const showPrResolved = showPr && pr && pr.number > 0; const showPrCreate = showPr && pr && pr.number <= 0; const isOwner = user && user.id === githubId.owner; @@ -778,7 +787,7 @@ class GithubComponent extends data.Component { - +
{showPrResolved && { {githubId.fullName} {"#" + githubId.tag} - {needsCommit && } - {showPrResolved && !needsCommit && } + {needsCommit && } + {showPrResolved && !needsCommit && } {diffFiles && } - - {master && } - {!isBlocksMode && } + + {isDefaultBranch && } + {!isBlocksMode && }
@@ -1142,8 +1151,8 @@ ${content} {displayDiffFiles.map(df => this.showDiff(df))} :
- {lf("No local changes found.")} -
; + {lf("No local changes found.")} + ; } } @@ -1153,10 +1162,10 @@ class MessageComponent extends sui.StatelessUIElement { this.handleSwitchMasterBranch = this.handleSwitchMasterBranch.bind(this); } - private handleSwitchMasterBranch(e: React.MouseEvent) { + private async handleSwitchMasterBranch(e: React.MouseEvent) { pxt.tickEvent("github.branch.switch"); e.stopPropagation(); - this.props.parent.switchBranchAsync("master"); + this.props.parent.switchBranchAsync(); } renderCore() { @@ -1207,7 +1216,7 @@ class MessageComponent extends sui.StatelessUIElement { interface GitHubViewProps { githubId: pxt.github.ParsedRepo; needsToken: boolean; - master: boolean; + isDefaultBranch: boolean; parent: GithubComponent; gs: pxt.github.GitJson; isBlocks: boolean; @@ -1357,7 +1366,7 @@ class ReleaseZone extends sui.StatelessUIElement { private handleBumpClick(e: React.MouseEvent) { pxt.tickEvent("github.releasezone.bump", undefined, { interactiveConsent: true }); e.stopPropagation(); - const { needsCommit, master } = this.props; + const { needsCommit, isDefaultBranch } = this.props; const header = this.props.parent.props.parent.state.header; if (needsCommit) core.confirmAsync({ @@ -1366,10 +1375,10 @@ class ReleaseZone extends sui.StatelessUIElement { agreeLbl: lf("Ok"), hideAgree: true }); - else if (!master) + else if (!isDefaultBranch) core.confirmAsync({ - header: lf("Checkout the master branch..."), - body: lf("You need to checkout the master branch to create a release."), + header: lf("Checkout the default branch..."), + body: lf("You need to checkout the default branch to create a release."), agreeLbl: lf("Ok"), hideAgree: true }); diff --git a/webapp/src/package.ts b/webapp/src/package.ts index af90483418a0..049a600a167d 100644 --- a/webapp/src/package.ts +++ b/webapp/src/package.ts @@ -936,7 +936,7 @@ data.mountVirtualApi("pkg-git-pr", { const ghid = f.getPkgId() == "this" && header && header.githubId; if (!ghid) return Promise.resolve(missing); const parsed = pxt.github.parseRepoId(ghid); - if (!parsed || !parsed.tag || parsed.tag == "master") return Promise.resolve(missing); + if (!parsed || !parsed.tag || pxt.github.isDefaultBranch(parsed.tag)) return Promise.resolve(missing); return pxt.github.findPRNumberforBranchAsync(parsed.fullName, parsed.tag) .catch(e => missing); }, diff --git a/webapp/src/workspace.ts b/webapp/src/workspace.ts index 57050a427e99..d35b13e4e341 100644 --- a/webapp/src/workspace.ts +++ b/webapp/src/workspace.ts @@ -370,7 +370,7 @@ interface ProjectChanges { header: Change[], files: Change[], } -function computeChangeSummary(a: {header: Header, text: ScriptText}, b: {header: Header, text: ScriptText}): ProjectChanges { +function computeChangeSummary(a: { header: Header, text: ScriptText }, b: { header: Header, text: ScriptText }): ProjectChanges { const aHdr = a.header || {} as Header const bHdr = b.header || {} as Header const aTxt = a.text || {} @@ -383,22 +383,22 @@ function computeChangeSummary(a: {header: Header, text: ScriptText}, b: {header: const hasHdrChanged = (k: HeaderK) => hasObjChanged(aHdr[k], bHdr[k]) const hdrChanges = hdrKeys.filter(hasHdrChanged) const hdrDels = hdrChanges.filter(k => (k in aHdr) && !(k in bHdr)) - .map(k => ({kind: 'del', key: k, oldVal: aHdr[k]}) as Change) + .map(k => ({ kind: 'del', key: k, oldVal: aHdr[k] }) as Change) const hdrAdds = hdrChanges.filter(k => !(k in aHdr) && (k in bHdr)) - .map(k => ({kind: 'add', key: k, newVal: bHdr[k]}) as Change) + .map(k => ({ kind: 'add', key: k, newVal: bHdr[k] }) as Change) const hdrMods = hdrChanges.filter(k => (k in aHdr) && (k in bHdr)) - .map(k => ({kind: 'mod', key: k, oldVal: aHdr[k], newVal: bHdr[k]}) as Change) + .map(k => ({ kind: 'mod', key: k, oldVal: aHdr[k], newVal: bHdr[k] }) as Change) // files const filenames = U.unique([...Object.keys(aTxt), ...Object.keys(bTxt)], s => s) const hasFileChanged = (filename: string) => aTxt[filename] !== bTxt[filename] const fileChanges = filenames.filter(hasFileChanged) const fileDels = fileChanges.filter(k => (k in aTxt) && !(k in bTxt) && !!b.text) - .map(k => ({kind: 'del', key: k, oldVal: aTxt[k].length}) as Change) + .map(k => ({ kind: 'del', key: k, oldVal: aTxt[k].length }) as Change) const fileAdds = fileChanges.filter(k => !(k in aTxt) && (k in bTxt)) - .map(k => ({kind: 'add', key: k, newVal: bTxt[k].length}) as Change) + .map(k => ({ kind: 'add', key: k, newVal: bTxt[k].length }) as Change) const fileMods = fileChanges.filter(k => (k in aTxt) && (k in bTxt)) - .map(k => ({kind: 'mod', key: k, oldVal: aTxt[k].length, newVal: bTxt[k].length}) as Change) + .map(k => ({ kind: 'mod', key: k, oldVal: aTxt[k].length, newVal: bTxt[k].length }) as Change) return { header: [...hdrDels, ...hdrAdds, ...hdrMods], @@ -408,7 +408,7 @@ function computeChangeSummary(a: {header: Header, text: ScriptText}, b: {header: // useful for debugging function stringifyChangeSummary(diff: ProjectChanges): string { const indent = (s: string) => '\t' + s - const changeToStr = (c: Change) => `${c.kind} ${c.key}: (${c.oldVal || ''}) => (${c.newVal || ''})` + const changeToStr = (c: Change) => `${c.kind} ${c.key}: (${c.oldVal || ''}) => (${c.newVal || ''})` let res = '' const hdrDels = diff.header.filter(k => k.kind === 'del') @@ -442,7 +442,7 @@ export async function partialSaveAsync(id: string, filename: string, content: st pxt.tickEvent(`workspace.invalidSaveToUnknownProject`); return; } - const newTxt = {...await getTextAsync(id)} + const newTxt = { ...await getTextAsync(id) } newTxt[filename] = content; return saveAsync(prev.header, newTxt); } @@ -479,7 +479,7 @@ export async function saveAsync(h: Header, text?: ScriptText, fromCloudSync?: bo return true } const prevProj = e - const allChanges = computeChangeSummary(prevProj, {header: h, text}) + const allChanges = computeChangeSummary(prevProj, { header: h, text }) const ignoredFiles = [GIT_JSON, pxt.SIMSTATE_JSON, pxt.SERIAL_EDITOR_FILE] const ignoredHeaderFields: (keyof Header)[] = ['recentUse', 'modificationTime', 'cloudCurrent', '_rev', '_id' as keyof Header, 'cloudVersion'] const userChanges: ProjectChanges = { @@ -801,10 +801,10 @@ export async function hasMergeConflictMarkersAsync(hd: Header): Promise export async function prAsync(hd: Header, commitId: string, msg: string) { let parsed = pxt.github.parseRepoId(hd.githubId) // merge conflict - create a Pull Request - const branchName = await pxt.github.getNewBranchNameAsync(parsed.slug, "merge-") - await pxt.github.createNewBranchAsync(parsed.slug, branchName, commitId) - const url = await pxt.github.createPRFromBranchAsync(parsed.slug, parsed.tag, branchName, msg) - // force user back to master - we will instruct them to merge PR in github.com website + const branchName = await pxt.github.getNewBranchNameAsync(parsed.fullName, "merge-") + await pxt.github.createNewBranchAsync(parsed.fullName, branchName, commitId) + const url = await pxt.github.createPRFromBranchAsync(parsed.fullName, parsed.tag, branchName, msg) + // force user back to default branch - we will instruct them to merge PR in github.com website // and sync here to get the changes let headCommit = await pxt.github.getRefAsync(parsed.slug, parsed.tag) await githubUpdateToAsync(hd, { @@ -911,7 +911,7 @@ export async function commitAsync(hd: Header, options: CommitOptions = {}) { // add compiled javascript to be run in github pages if (pxt.appTarget.appTheme.githubCompiledJs && options.binaryJs - && (!parsed.tag || parsed.tag == "master")) { + && (!parsed.tag || pxt.github.isDefaultBranch(parsed.tag))) { const v = cfg.version || "0.0.0"; const opts: compiler.CompileOptions = { jsMetaVersion: v @@ -966,10 +966,10 @@ export async function commitAsync(hd: Header, options: CommitOptions = {}) { files, saveTag: options.createRelease }) - if (options.createRelease) { + if (options.createRelease && pxt.github.isDefaultBranch(parsed.tag)) { await pxt.github.createReleaseAsync(parsed.slug, options.createRelease, newCommit) // ensure pages are on - await pxt.github.enablePagesAsync(parsed.slug); + await pxt.github.enablePagesAsync(parsed.slug, parsed.tag); // clear the cloud cache await pxt.github.listRefsAsync(parsed.slug, "tags", true, true); } @@ -1218,7 +1218,12 @@ async function githubUpdateToAsync(hd: Header, options: UpdateOptions) { export async function exportToGithubAsync(hd: Header, repoid: string) { const parsed = pxt.github.parseRepoId(repoid); const pfiles = pxt.template.packageFiles(hd.name); - await pxt.github.putFileAsync(parsed.fullName, ".gitignore", pfiles[".gitignore"]); + if (!parsed.tag) { + const packagesConfig = await pxt.packagesConfigAsync() + const repo = await pxt.github.repoAsync(parsed.slug, packagesConfig) + parsed.tag = repo.defaultBranch + } + await pxt.github.putFileAsync(parsed.fullName, parsed.tag, ".gitignore", pfiles[".gitignore"]); const sha = await pxt.github.getRefAsync(parsed.slug, parsed.tag) const commit = await pxt.github.getCommitAsync(parsed.slug, sha) const files = await getTextAsync(hd.id) @@ -1434,7 +1439,7 @@ export async function initializeGithubRepoAsync(hd: Header, repoid: string, forc // try enable github pages try { - await pxt.github.enablePagesAsync(parsed.slug); + await pxt.github.enablePagesAsync(parsed.slug, parsed.tag); } catch (e) { pxt.reportException(e); } @@ -1450,7 +1455,14 @@ export async function importGithubAsync(id: string): Promise
{ let isEmpty = false let forceTemplateFiles = false; try { + const packagesConfig = await pxt.packagesConfigAsync() + const repo = await pxt.github.repoAsync(parsed.slug, packagesConfig) + if (!repo) + U.userError(`unable to find repository`) + parsed.tag = repo.defaultBranch sha = await pxt.github.getRefAsync(parsed.slug, parsed.tag) + if (!sha) + U.userError(`unable to find branch`) // if the repo does not have a pxt.json file, treat as empty // (must be done before) const commit = await pxt.github.getCommitAsync(parsed.slug, sha) @@ -1480,7 +1492,7 @@ export async function importGithubAsync(id: string): Promise
{ if (pxt.shell.isReadOnly()) U.userError(lf("This repository looks empty.")); await cloudsync.ensureGitHubTokenAsync(); - await pxt.github.putFileAsync(parsed.fullName, ".gitignore", "# Initial\n"); + await pxt.github.putFileAsync(parsed.fullName, parsed.tag, ".gitignore", "# Initial\n"); isEmpty = true; forceTemplateFiles = true; sha = await pxt.github.getRefAsync(parsed.slug, parsed.tag) @@ -1620,7 +1632,7 @@ export function fireEvent(ev: pxt.editor.events.Event) { } // debug helpers -const _abrvStrs: {[key: string]: string} = {}; +const _abrvStrs: { [key: string]: string } = {}; let _abrvNextInt = 1; function dbgShorten(s: string): string { if (!s)