Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions contributions.json
Original file line number Diff line number Diff line change
Expand Up @@ -4804,6 +4804,11 @@
]
}
},
"gitlens.views.addPullRequestRemote": {
"label": "Add Pull Request Remote",
"icon": "$(add)",
"enablement": "!operationInProgress"
},
"gitlens.views.addRemote": {
"label": "Add Remote...",
"icon": "$(add)",
Expand Down
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7629,6 +7629,12 @@
"title": "Add Co-authors...",
"icon": "$(person-add)"
},
{
"command": "gitlens.views.addPullRequestRemote",
"title": "Add Pull Request Remote",
"icon": "$(add)",
"enablement": "!operationInProgress"
},
{
"command": "gitlens.views.addRemote",
"title": "Add Remote...",
Expand Down Expand Up @@ -11330,6 +11336,10 @@
"command": "gitlens.views.addAuthors",
"when": "false"
},
{
"command": "gitlens.views.addPullRequestRemote",
"when": "false"
},
{
"command": "gitlens.views.addRemote",
"when": "false"
Expand Down
1 change: 1 addition & 0 deletions src/constants.commands.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export type ContributedCommands =
| 'gitlens.views.addAuthor'
| 'gitlens.views.addAuthor.multi'
| 'gitlens.views.addAuthors'
| 'gitlens.views.addPullRequestRemote'
| 'gitlens.views.addRemote'
| 'gitlens.views.applyChanges'
| 'gitlens.views.associateIssueWithBranch'
Expand Down
3 changes: 3 additions & 0 deletions src/constants.commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ type InternalPlusCommands =
| 'gitlens.plus.showPlans'
| 'gitlens.plus.validate';

type InternalPullRequestViewCommands = 'gitlens.views.addPullRequestRemote';

type InternalScmGroupedViewCommands =
| 'gitlens.views.scm.grouped.welcome.dismiss'
| 'gitlens.views.scm.grouped.welcome.restore';
Expand Down Expand Up @@ -221,6 +223,7 @@ type InternalGlCommands =
| InternalHomeWebviewViewCommands
| InternalLaunchPadCommands
| InternalPlusCommands
| InternalPullRequestViewCommands
| InternalScmGroupedViewCommands
| InternalSearchAndCompareViewCommands
| InternalTimelineWebviewViewCommands
Expand Down
34 changes: 18 additions & 16 deletions src/git/utils/-webview/pullRequest.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { createRevisionRange } from '../revision.utils';
export async function ensurePullRequestRefs(
pr: PullRequest,
repo: Repository,
options?: { promptMessage?: string },
options?: { silent?: true; promptMessage?: never } | { silent?: never; promptMessage?: string },
refs?: PullRequestComparisonRefs,
): Promise<LeftRightCommitCountResult | undefined> {
if (pr.refs == null) return undefined;
Expand All @@ -32,7 +32,7 @@ export async function ensurePullRequestRefs(
export async function ensurePullRequestRemote(
pr: PullRequest,
repo: Repository,
options?: { promptMessage?: string },
options?: { silent?: true; promptMessage?: never } | { silent?: never; promptMessage?: string },
): Promise<boolean> {
const identity = getRepositoryIdentityForPullRequest(pr);
if (identity.remote.url == null) return false;
Expand All @@ -51,20 +51,22 @@ export async function ensurePullRequestRemote(

const confirm = { title: 'Add Remote' };
const cancel = { title: 'Cancel', isCloseAffordance: true };
const result = await window.showInformationMessage(
`${
options?.promptMessage ?? `Unable to find a remote for PR #${pr.id}.`
}\nWould you like to add a remote for '${identity.provider.repoDomain}?`,
{ modal: true },
confirm,
cancel,
);

if (result === confirm) {
await repo.git
.remotes()
.addRemoteWithResult?.(identity.provider.repoDomain, identity.remote.url, { fetch: true });
return true;
if (!options?.silent) {
const result = await window.showInformationMessage(
`${
options?.promptMessage ?? `Unable to find a remote for PR #${pr.id}.`
}\nWould you like to add a remote for '${identity.provider.repoDomain}?`,
{ modal: true },
confirm,
cancel,
);

if (result === confirm) {
await repo.git
.remotes()
.addRemoteWithResult?.(identity.provider.repoDomain, identity.remote.url, { fetch: true });
return true;
}
}

return false;
Expand Down
18 changes: 11 additions & 7 deletions src/plus/launchpad/launchpadProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export type LaunchpadItem = LaunchpadPullRequest & {

export type OpenRepository = {
repo: Repository;
remote: GitRemote;
remote?: GitRemote;
localBranch?: GitBranch;
};

Expand Down Expand Up @@ -551,12 +551,16 @@ export class LaunchpadProvider implements Disposable {
): Promise<OpenRepository | undefined> {
if (pr.repoIdentity.remote.url == null) return undefined;

const match =
matchingRemoteMap.get(pr.repoIdentity.remote.url) ??
(pr.underlyingPullRequest?.refs?.base?.url
? matchingRemoteMap.get(pr.underlyingPullRequest.refs.base.url)
: undefined);
if (match == null) return undefined;
let match = matchingRemoteMap.get(pr.repoIdentity.remote.url);
if (match == null) {
if (pr.underlyingPullRequest?.refs?.base?.url == null) return undefined;

match = matchingRemoteMap.get(pr.underlyingPullRequest.refs.base.url);
if (match == null) return undefined;

const [repo] = match;
return { repo: repo };
}

const [repo, remote] = match;

Expand Down
31 changes: 28 additions & 3 deletions src/views/nodes/pullRequestNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,24 @@ import type { GitBranchReference } from '../../git/models/reference';
import type { Repository } from '../../git/models/repository';
import { getAheadBehindFilesQuery, getCommitsQuery } from '../../git/queryResults';
import { getIssueOrPullRequestMarkdownIcon, getIssueOrPullRequestThemeIcon } from '../../git/utils/-webview/icons';
import { ensurePullRequestRefs, getOrOpenPullRequestRepository } from '../../git/utils/-webview/pullRequest.utils';
import { getComparisonRefsForPullRequest } from '../../git/utils/pullRequest.utils';
import {
ensurePullRequestRefs,
ensurePullRequestRemote,
getOrOpenPullRequestRepository,
} from '../../git/utils/-webview/pullRequest.utils';
import {
getComparisonRefsForPullRequest,
getRepositoryIdentityForPullRequest,
} from '../../git/utils/pullRequest.utils';
import { createRevisionRange } from '../../git/utils/revision.utils';
import { createCommand } from '../../system/-webview/command';
import { pluralize } from '../../system/string';
import type { ViewsWithCommits } from '../viewBase';
import { CacheableChildrenViewNode } from './abstract/cacheableChildrenViewNode';
import type { ClipboardType, ViewNode } from './abstract/viewNode';
import { ContextValues, getViewNodeId } from './abstract/viewNode';
import { CodeSuggestionsNode } from './codeSuggestionsNode';
import { MessageNode } from './common';
import { CommandMessageNode, MessageNode } from './common';
import { ResultsCommitsNode } from './resultsCommitsNode';
import { ResultsFilesNode } from './resultsFilesNode';

Expand Down Expand Up @@ -159,6 +167,23 @@ export async function getPullRequestChildren(

const repoPath = repo.path;
const refs = getComparisonRefsForPullRequest(repoPath, pullRequest.refs!);
const identity = getRepositoryIdentityForPullRequest(pullRequest);
if (!(await ensurePullRequestRemote(pullRequest, repo, { silent: true }))) {
return [
new CommandMessageNode(
view,
parent,
createCommand<[ViewNode, PullRequest, Repository]>(
'gitlens.views.addPullRequestRemote',
'Add Pull Request Remote...',
parent,
pullRequest,
repo,
),
`Missing remote '${identity.provider.repoDomain}'. Click to add.`,
),
];
}

const counts = await ensurePullRequestRefs(
pullRequest,
Expand Down
14 changes: 14 additions & 0 deletions src/views/viewCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import * as StashActions from '../git/actions/stash';
import * as TagActions from '../git/actions/tag';
import * as WorktreeActions from '../git/actions/worktree';
import { GitUri } from '../git/gitUri';
import type { PullRequest } from '../git/models/pullRequest';
import { RemoteResourceType } from '../git/models/remoteResource';
import type { Repository } from '../git/models/repository';
import { deletedOrMissing } from '../git/models/revision';
import {
ensurePullRequestRefs,
Expand Down Expand Up @@ -238,6 +240,8 @@ export class ViewCommands implements Disposable {
registerViewCommand('gitlens.views.addAuthor', this.addAuthor, this),
registerViewCommand('gitlens.views.addAuthor.multi', this.addAuthor, this, true),

registerViewCommand('gitlens.views.addPullRequestRemote', this.addPullRequestRemote, this),

registerViewCommand(
'gitlens.views.openBranchOnRemote',
n => executeCommand(GlCommand.OpenBranchOnRemote, n),
Expand Down Expand Up @@ -481,6 +485,16 @@ export class ViewCommands implements Disposable {
return RemoteActions.add(getNodeRepoPath(node));
}

@log()
private async addPullRequestRemote(node: ViewNode, pr: PullRequest, repo: Repository) {
const identity = getRepositoryIdentityForPullRequest(pr);
if (identity.remote?.url == null) return;
await repo.git
.remotes()
.addRemoteWithResult?.(identity.provider.repoDomain, identity.remote.url, { fetch: true });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.addRemoteWithResult?.(identity.provider.repoDomain, identity.remote.url, { fetch: true });
.addRemote?.(identity.provider.repoDomain, identity.remote.url, { fetch: true });

Since we aren't returning the remote we don't need to wait for it

return node.view.refreshNode(node, true);
}

@log()
private applyChanges(node: ViewRefFileNode) {
if (node.is('results-file')) {
Expand Down