in src/view/reviewManager.ts [685:789]
public async publishBranch(branch: Branch): Promise<Branch | undefined> {
const potentialTargetRemotes = await this._folderRepoManager.getAllGitHubRemotes();
let selectedRemote = (await this.getRemote(
potentialTargetRemotes,
`Pick a remote to publish the branch '${branch.name}' to:`,
))!.remote;
if (!selectedRemote || branch.name === undefined) {
return;
}
const githubRepo = this._folderRepoManager.createGitHubRepository(
selectedRemote,
this._folderRepoManager.credentialStore,
);
const permission = await githubRepo.getViewerPermission();
if (
permission === ViewerPermission.Read ||
permission === ViewerPermission.Triage ||
permission === ViewerPermission.Unknown
) {
// No permission to publish the branch to the chosen remote. Offer to fork.
const fork = await this._folderRepoManager.tryOfferToFork(githubRepo);
if (!fork) {
return;
}
selectedRemote = this._folderRepoManager.getGitHubRemotes().find(element => element.remoteName === fork);
}
if (!selectedRemote) {
return;
}
const remote: Remote = selectedRemote;
return new Promise<Branch | undefined>(async resolve => {
const inputBox = vscode.window.createInputBox();
inputBox.value = branch.name!;
inputBox.ignoreFocusOut = true;
inputBox.prompt =
potentialTargetRemotes.length === 1
? `The branch '${branch.name}' is not published yet, pick a name for the upstream branch`
: 'Pick a name for the upstream branch';
const validate = async function (value: string) {
try {
inputBox.busy = true;
const remoteBranch = await this._reposManager.getBranch(remote, value);
if (remoteBranch) {
inputBox.validationMessage = `Branch ${value} already exists in ${remote.owner}/${remote.repositoryName}`;
} else {
inputBox.validationMessage = undefined;
}
} catch (e) {
inputBox.validationMessage = undefined;
}
inputBox.busy = false;
};
await validate(branch.name!);
inputBox.onDidChangeValue(validate.bind(this));
inputBox.onDidAccept(async () => {
inputBox.validationMessage = undefined;
inputBox.hide();
try {
// since we are probably pushing a remote branch with a different name, we use the complete syntax
// git push -u origin local_branch:remote_branch
await this._repository.push(remote.remoteName, `${branch.name}:${inputBox.value}`, true);
} catch (err) {
if (err.gitErrorCode === GitErrorCodes.PushRejected) {
vscode.window.showWarningMessage(
`Can't push refs to remote, try running 'git pull' first to integrate with your change`,
{
modal: true,
},
);
resolve(undefined);
}
if (err.gitErrorCode === GitErrorCodes.RemoteConnectionError) {
vscode.window.showWarningMessage(
`Could not read from remote repository '${remote.remoteName}'. Please make sure you have the correct access rights and the repository exists.`,
{
modal: true,
},
);
resolve(undefined);
}
// we can't handle the error
throw err;
}
// we don't want to wait for repository status update
const latestBranch = await this._repository.getBranch(branch.name!);
if (!latestBranch || !latestBranch.upstream) {
resolve(undefined);
}
resolve(latestBranch);
});
inputBox.show();
});
}