Skip to content

Commit a04c707

Browse files
committed
Fixes virtual repos opened from forked PRs
1 parent d3b4012 commit a04c707

File tree

4 files changed

+94
-53
lines changed

4 files changed

+94
-53
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
1313
### Fixed
1414

1515
- Fixes [#3592](https://github.com/gitkraken/vscode-gitlens/issues/3592) - Connecting to an integration via Remotes view (but likely others) doesn't work
16+
- Fixes an issue where virtual repositories for GitHub PRs from forks wouldn't load properly
1617

1718
## [15.5.1] - 2024-09-16
1819

src/git/gitUri.authority.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,17 @@ export function decodeGitLensRevisionUriAuthority<T>(authority: string): T {
77
export function encodeGitLensRevisionUriAuthority<T>(metadata: T): string {
88
return encodeUtf8Hex(JSON.stringify(metadata));
99
}
10+
11+
export function decodeRemoteHubAuthority<T>(authority: string): { scheme: string; metadata: T | undefined } {
12+
const [scheme, encoded] = authority.split('+');
13+
14+
let metadata: T | undefined;
15+
if (encoded) {
16+
try {
17+
const data = JSON.parse(decodeUtf8Hex(encoded));
18+
metadata = data as T;
19+
} catch {}
20+
}
21+
22+
return { scheme: scheme, metadata: metadata };
23+
}

src/git/gitUri.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { decodeUtf8Hex } from '@env/hex';
21
import { Uri } from 'vscode';
32
import { getQueryDataFromScmGitUri } from '../@types/vscode.git.uri';
43
import { Schemes } from '../constants';
@@ -12,7 +11,7 @@ import { formatPath } from '../system/vscode/formatPath';
1211
import { getBestPath, relativeDir, splitPath } from '../system/vscode/path';
1312
import { isVirtualUri } from '../system/vscode/utils';
1413
import type { RevisionUriData } from './gitProvider';
15-
import { decodeGitLensRevisionUriAuthority } from './gitUri.authority';
14+
import { decodeGitLensRevisionUriAuthority, decodeRemoteHubAuthority } from './gitUri.authority';
1615
import { uncommittedStaged } from './models/constants';
1716
import type { GitFile } from './models/file';
1817
import { isUncommitted, isUncommittedStaged, shortenRevision } from './models/reference';
@@ -93,7 +92,7 @@ export class GitUri extends (Uri as any as UriEx) {
9392
const [, owner, repo] = uri.path.split('/', 3);
9493
this.repoPath = uri.with({ path: `/${owner}/${repo}` }).toString();
9594

96-
const data = decodeRemoteHubAuthority<GitHubAuthorityMetadata>(uri);
95+
const data = decodeRemoteHubAuthority<GitHubAuthorityMetadata>(uri.authority);
9796

9897
let ref = data.metadata?.ref?.id;
9998
if (commitOrRepoPath != null && typeof commitOrRepoPath !== 'string') {
@@ -336,17 +335,3 @@ export const unknownGitUri = Object.freeze(new GitUri());
336335
export function isGitUri(uri: any): uri is GitUri {
337336
return uri instanceof GitUri;
338337
}
339-
340-
function decodeRemoteHubAuthority<T>(uri: Uri): { scheme: string; metadata: T | undefined } {
341-
const [scheme, encoded] = uri.authority.split('+');
342-
343-
let metadata: T | undefined;
344-
if (encoded) {
345-
try {
346-
const data = JSON.parse(decodeUtf8Hex(encoded));
347-
metadata = data as T;
348-
} catch {}
349-
}
350-
351-
return { scheme: scheme, metadata: metadata };
352-
}

src/plus/integrations/providers/github/githubGitProvider.ts

Lines changed: 77 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import type {
3939
ScmRepository,
4040
} from '../../../../git/gitProvider';
4141
import { GitUri } from '../../../../git/gitUri';
42+
import { decodeRemoteHubAuthority } from '../../../../git/gitUri.authority';
4243
import type { GitBlame, GitBlameAuthor, GitBlameLine, GitBlameLines } from '../../../../git/models/blame';
4344
import type { BranchSortOptions } from '../../../../git/models/branch';
4445
import { getBranchId, getBranchNameWithoutRemote, GitBranch, sortBranches } from '../../../../git/models/branch';
@@ -103,7 +104,7 @@ import { serializeWebviewItemContext } from '../../../../system/webview';
103104
import type { CachedBlame, CachedLog, TrackedGitDocument } from '../../../../trackers/trackedDocument';
104105
import { GitDocumentState } from '../../../../trackers/trackedDocument';
105106
import type { GitHubAuthorityMetadata, Metadata, RemoteHubApi } from '../../../remotehub';
106-
import { getRemoteHubApi, HeadType } from '../../../remotehub';
107+
import { getRemoteHubApi, HeadType, RepositoryRefType } from '../../../remotehub';
107108
import type {
108109
GraphBranchContextValue,
109110
GraphItemContext,
@@ -116,6 +117,7 @@ import type {
116117
} from '../../authentication/integrationAuthentication';
117118
import { HostingIntegrationId } from '../models';
118119
import type { GitHubApi } from './github';
120+
import type { GitHubBranch } from './models';
119121
import { fromCommitFileStatus } from './models';
120122

121123
const doubleQuoteRegex = /"/g;
@@ -924,7 +926,36 @@ export class GitHubGitProvider implements GitProvider, Disposable {
924926
const {
925927
values: [branch],
926928
} = await this.getBranches(repoPath, { filter: b => b.current });
927-
return branch;
929+
if (branch != null) return branch;
930+
931+
try {
932+
const { metadata } = await this.ensureRepositoryContext(repoPath!);
933+
934+
const revision = await metadata.getRevision();
935+
switch (revision.type) {
936+
case HeadType.Tag:
937+
case HeadType.Commit:
938+
return new GitBranch(
939+
this.container,
940+
repoPath!,
941+
revision.name,
942+
false,
943+
true,
944+
undefined,
945+
revision.revision,
946+
undefined,
947+
undefined,
948+
undefined,
949+
true,
950+
);
951+
}
952+
953+
return undefined;
954+
} catch (ex) {
955+
debugger;
956+
Logger.error(ex, getLogScope());
957+
return undefined;
958+
}
928959
}
929960

930961
@log({ args: { 1: false } })
@@ -946,11 +977,39 @@ export class GitHubGitProvider implements GitProvider, Disposable {
946977
try {
947978
const { metadata, github, session } = await this.ensureRepositoryContext(repoPath!);
948979

949-
const revision = await metadata.getRevision();
950-
const current = revision.type === 0 /* HeadType.Branch */ ? revision.name : undefined;
951-
952980
const branches: GitBranch[] = [];
953981

982+
function addBranches(container: Container, branch: GitHubBranch, current: boolean) {
983+
const date = new Date(
984+
configuration.get('advanced.commitOrdering') === 'author-date'
985+
? branch.target.authoredDate
986+
: branch.target.committedDate,
987+
);
988+
const ref = branch.target.oid;
989+
990+
branches.push(
991+
new GitBranch(container, repoPath!, branch.name, false, current, date, ref, {
992+
name: `origin/${branch.name}`,
993+
missing: false,
994+
}),
995+
new GitBranch(container, repoPath!, `origin/${branch.name}`, true, false, date, ref),
996+
);
997+
}
998+
999+
let currentBranch: string | undefined;
1000+
1001+
const revision = await metadata.getRevision();
1002+
switch (revision.type) {
1003+
case HeadType.Branch:
1004+
currentBranch = revision.name;
1005+
break;
1006+
case HeadType.RemoteBranch: {
1007+
const index = revision.name.indexOf(':');
1008+
currentBranch = index === -1 ? revision.name : revision.name.substring(index + 1);
1009+
break;
1010+
}
1011+
}
1012+
9541013
let cursor = options?.paging?.cursor;
9551014
const loadAll = cursor == null;
9561015

@@ -963,37 +1022,7 @@ export class GitHubGitProvider implements GitProvider, Disposable {
9631022
);
9641023

9651024
for (const branch of result.values) {
966-
const date = new Date(
967-
configuration.get('advanced.commitOrdering') === 'author-date'
968-
? branch.target.authoredDate
969-
: branch.target.committedDate,
970-
);
971-
const ref = branch.target.oid;
972-
973-
branches.push(
974-
new GitBranch(
975-
this.container,
976-
repoPath!,
977-
branch.name,
978-
false,
979-
branch.name === current,
980-
date,
981-
ref,
982-
{
983-
name: `origin/${branch.name}`,
984-
missing: false,
985-
},
986-
),
987-
new GitBranch(
988-
this.container,
989-
repoPath!,
990-
`origin/${branch.name}`,
991-
true,
992-
false,
993-
date,
994-
ref,
995-
),
996-
);
1025+
addBranches(this.container, branch, branch.name === currentBranch);
9971026
}
9981027

9991028
if (!result.paging?.more || !loadAll) return { ...result, values: branches };
@@ -3436,6 +3465,18 @@ export class GitHubGitProvider implements GitProvider, Disposable {
34363465
throw new OpenVirtualRepositoryError(repoPath, OpenVirtualRepositoryErrorReason.NotAGitHubRepository);
34373466
}
34383467

3468+
const data = decodeRemoteHubAuthority<GitHubAuthorityMetadata>(uri.authority);
3469+
// If the virtual repository is opened to a PR, then we need to ensure the owner is the owner of the current branch
3470+
if (data.metadata?.ref?.type === RepositoryRefType.PullRequest) {
3471+
const revision = await metadata.getRevision();
3472+
if (revision.type === HeadType.RemoteBranch) {
3473+
const [remote] = revision.name.split(':');
3474+
if (remote !== metadata.repo.owner) {
3475+
metadata.repo.owner = remote;
3476+
}
3477+
}
3478+
}
3479+
34393480
let github;
34403481
let session;
34413482
try {

0 commit comments

Comments
 (0)