Skip to content

Commit

Permalink
On PR to submodule parent package was forked instead of submodule (#6565
Browse files Browse the repository at this point in the history
)

Fixes #6492
  • Loading branch information
alexr00 authored Dec 18, 2024
1 parent 20c6ea9 commit b058a0e
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 167 deletions.
8 changes: 5 additions & 3 deletions src/github/createPRViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1115,9 +1115,11 @@ export class CreatePullRequestViewProvider extends BaseCreatePullRequestViewProv

if (pushRemote && createdPushRemote) {
Logger.appendLine(`Found push remote ${pushRemote.name} for ${compareOwner}/${compareRepositoryName} and branch ${compareBranchName}`, CreatePullRequestViewProvider.ID);
await this._folderRepositoryManager.repository.push(pushRemote.name, compareBranchName, true);
await this._folderRepositoryManager.repository.status();
return { compareUpstream: createdPushRemote, repo: this._folderRepositoryManager.findRepo(byRemoteName(createdPushRemote.remoteName)) };
const actualPushRemote = await this._folderRepositoryManager.publishBranch(createdPushRemote, compareBranchName);
if (!actualPushRemote) {
return undefined;
}
return { compareUpstream: actualPushRemote, repo: this._folderRepositoryManager.findRepo(byRemoteName(actualPushRemote.remoteName)) };
}
}

Expand Down
64 changes: 62 additions & 2 deletions src/github/folderRepositoryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2581,13 +2581,14 @@ export class FolderRepositoryManager extends Disposable {
const workingRemoteName: string =
matchingRepo.state.remotes.length > 1 ? 'origin' : matchingRepo.state.remotes[0].name;
progress.report({ message: vscode.l10n.t('Adding remotes. This may take a few moments.') });
const startingRepoCount = this.gitHubRepositories.length;
await matchingRepo.renameRemote(workingRemoteName, 'upstream');
await matchingRepo.addRemote(workingRemoteName, result);
// Now the extension is responding to all the git changes.
await new Promise<void>(resolve => {
if (this.gitHubRepositories.length === 0) {
if (this.gitHubRepositories.length === startingRepoCount) {
const disposable = this.onDidChangeRepositories(() => {
if (this.gitHubRepositories.length > 0) {
if (this.gitHubRepositories.length > startingRepoCount) {
disposable.dispose();
resolve();
}
Expand Down Expand Up @@ -2640,6 +2641,65 @@ export class FolderRepositoryManager extends Disposable {
}
}

public async publishBranch(pushRemote: Remote, branchName: string): Promise<GitHubRemote | undefined> {
const githubRepo = await this.createGitHubRepository(
pushRemote,
this.credentialStore,
);
const permission = await githubRepo.getViewerPermission();
let selectedRemote: GitHubRemote | undefined;
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.tryOfferToFork(githubRepo);
if (!fork) {
return;
}

selectedRemote = (await this.getGitHubRemotes()).find(element => element.remoteName === fork);
} else {
selectedRemote = (await this.getGitHubRemotes()).find(element => element.remoteName === pushRemote.remoteName);
}

if (!selectedRemote) {
return;
}

try {
await this._repository.push(selectedRemote.remoteName, branchName, true);
await this._repository.status();
return selectedRemote;
} catch (err) {
if (err.gitErrorCode === GitErrorCodes.PushRejected) {
vscode.window.showWarningMessage(
vscode.l10n.t(`Can't push refs to remote, try running 'git pull' first to integrate with your change`),
{
modal: true,
},
);

return undefined;
}

if (err.gitErrorCode === GitErrorCodes.RemoteConnectionError) {
vscode.window.showWarningMessage(
vscode.l10n.t(`Could not read from remote repository '{0}'. Please make sure you have the correct access rights and the repository exists.`, selectedRemote.remoteName),
{
modal: true,
},
);

return undefined;
}

// we can't handle the error
throw err;
}
}

public getTitleAndDescriptionProvider(searchTerm?: string) {
return this._git.getTitleAndDescriptionProvider(searchTerm);
}
Expand Down
163 changes: 1 addition & 162 deletions src/view/reviewManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { formatError, groupBy, onceEvent } from '../common/utils';
import { FOCUS_REVIEW_MODE } from '../constants';
import { GitHubCreatePullRequestLinkProvider } from '../github/createPRLinkProvider';
import { FolderRepositoryManager } from '../github/folderRepositoryManager';
import { GitHubRepository, ViewerPermission } from '../github/githubRepository';
import { GitHubRepository } from '../github/githubRepository';
import { GithubItemStateEnum } from '../github/interface';
import { PullRequestGitHelper, PullRequestMetadata } from '../github/pullRequestGitHelper';
import { IResolvedPullRequestModel, PullRequestModel } from '../github/pullRequestModel';
Expand All @@ -43,7 +43,6 @@ import { getInMemPRFileSystemProvider, provideDocumentContentForChangeModel } fr
import { PullRequestChangesTreeDataProvider } from './prChangesTreeDataProvider';
import { ProgressHelper } from './progress';
import { PullRequestsTreeDataProvider } from './prsTreeDataProvider';
import { RemoteQuickPickItem } from './quickpick';
import { ReviewCommentController, SuggestionInformation } from './reviewCommentController';
import { ReviewModel } from './reviewModel';
import { GitFileChangeNode, gitFileChangeNodeFilter, RemoteFileChangeNode } from './treeNodes/fileChangeNode';
Expand Down Expand Up @@ -1144,166 +1143,6 @@ export class ReviewManager extends Disposable {
this.statusBarItem.show();
}

public async publishBranch(branch: Branch): Promise<Branch | undefined> {
const potentialTargetRemotes = await this._folderRepoManager.getAllGitHubRemotes();
let selectedRemote = (await this.getRemote(
potentialTargetRemotes,
vscode.l10n.t(`Pick a remote to publish the branch '{0}' to:`, branch.name!),
))!.remote;

if (!selectedRemote || branch.name === undefined) {
return;
}

const githubRepo = await 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 = (await 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
? vscode.l10n.t(`The branch '{0}' is not published yet, pick a name for the upstream branch`, branch.name!)
: vscode.l10n.t('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 = vscode.l10n.t(`Branch '{0}' already exists in {1}`, value, `${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(
vscode.l10n.t(`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(
vscode.l10n.t(`Could not read from remote repository '{0}'. Please make sure you have the correct access rights and the repository exists.`, remote.remoteName),
{
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();
});
}

private async getRemote(
potentialTargetRemotes: Remote[],
placeHolder: string,
defaultUpstream?: RemoteQuickPickItem,
): Promise<RemoteQuickPickItem | undefined> {
if (!potentialTargetRemotes.length) {
vscode.window.showWarningMessage(vscode.l10n.t(`No GitHub remotes found. Add a remote and try again.`));
return;
}

if (potentialTargetRemotes.length === 1 && !defaultUpstream) {
return RemoteQuickPickItem.fromRemote(potentialTargetRemotes[0]);
}

if (
potentialTargetRemotes.length === 1 &&
defaultUpstream &&
defaultUpstream.owner === potentialTargetRemotes[0].owner &&
defaultUpstream.name === potentialTargetRemotes[0].repositoryName
) {
return defaultUpstream;
}

let defaultUpstreamWasARemote = false;
const picks: RemoteQuickPickItem[] = potentialTargetRemotes.map(remote => {
const remoteQuickPick = RemoteQuickPickItem.fromRemote(remote);
if (defaultUpstream) {
const { owner, name } = defaultUpstream;
remoteQuickPick.picked = remoteQuickPick.owner === owner && remoteQuickPick.name === name;
if (remoteQuickPick.picked) {
defaultUpstreamWasARemote = true;
}
}
return remoteQuickPick;
});
if (!defaultUpstreamWasARemote && defaultUpstream) {
picks.unshift(defaultUpstream);
}

const selected: RemoteQuickPickItem | undefined = await vscode.window.showQuickPick<RemoteQuickPickItem>(
picks,
{
ignoreFocusOut: true,
placeHolder: placeHolder,
},
);

if (!selected) {
return;
}

return selected;
}

public async createPullRequest(compareBranch?: string): Promise<void> {
const postCreate = async (createdPR: PullRequestModel | undefined) => {
if (!createdPR) {
Expand Down

0 comments on commit b058a0e

Please sign in to comment.