Skip to content

Commit 8564a48

Browse files
committed
Fixes issue with incorrect local branch matching
Improves matching performance
1 parent 6d1115a commit 8564a48

File tree

1 file changed

+59
-32
lines changed

1 file changed

+59
-32
lines changed

src/plus/focus/focusProvider.ts

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import { CancellationError } from '../../errors';
77
import { openComparisonChanges } from '../../git/actions/commit';
88
import type { Account } from '../../git/models/author';
99
import type { GitBranch } from '../../git/models/branch';
10+
import { getLocalBranchByUpstream } from '../../git/models/branch';
1011
import type { SearchedIssue } from '../../git/models/issue';
1112
import type { SearchedPullRequest } from '../../git/models/pullRequest';
1213
import { getComparisonRefsForPullRequest } from '../../git/models/pullRequest';
1314
import type { GitRemote } from '../../git/models/remote';
1415
import type { Repository } from '../../git/models/repository';
1516
import type { CodeSuggestionCounts, Draft } from '../../gk/models/drafts';
16-
import { getPathFromProviderIdentity } from '../../gk/models/repositoryIdentities';
1717
import { executeCommand, registerCommand } from '../../system/command';
1818
import { configuration } from '../../system/configuration';
1919
import { getSettledValue } from '../../system/promise';
@@ -426,39 +426,57 @@ export class FocusProvider implements Disposable {
426426
);
427427
}
428428

429-
async getMatchingOpenRepository(pr: EnrichablePullRequest): Promise<OpenRepository | undefined> {
429+
async getMatchingOpenRepository(
430+
pr: EnrichablePullRequest,
431+
matchingRemoteMap: Map<string, [Repository, GitRemote]>,
432+
): Promise<OpenRepository | undefined> {
433+
if (pr.repoIdentity.remote.url == null) return undefined;
434+
435+
const match = matchingRemoteMap.get(pr.repoIdentity.remote.url);
436+
if (match == null) return undefined;
437+
438+
const [repo, remote] = match;
439+
const remoteBranchName = `${remote.name}/${pr.refs?.head.branch ?? pr.headRef?.name}`;
440+
const matchingLocalBranch = await getLocalBranchByUpstream(repo, remoteBranchName);
441+
442+
return { repo: repo, remote: remote, localBranch: matchingLocalBranch };
443+
}
444+
445+
private async getMatchingRemoteMap(actionableItems: FocusPullRequest[]) {
446+
const uniqueRemoteUrls = new Set<string>();
447+
for (const item of actionableItems) {
448+
if (item.repoIdentity.remote.url != null) {
449+
uniqueRemoteUrls.add(item.repoIdentity.remote.url);
450+
}
451+
}
452+
453+
// Get the repo/remote pairs for the unique remote urls
454+
const repoRemotes = new Map<string, [Repository, GitRemote]>();
455+
430456
for (const repo of this.container.git.openRepositories) {
431-
const matchingRemote = (
432-
await repo.getRemotes({
433-
filter: r =>
434-
r.matches(pr.repoIdentity.remote.url!) ||
435-
r.matches(
436-
pr.repoIdentity.provider.domain,
437-
getPathFromProviderIdentity(pr.repoIdentity.provider),
438-
),
439-
})
440-
)?.[0];
441-
if (matchingRemote == null) continue;
442-
443-
const matchingRemoteBranch = (
444-
await repo.getBranches({
445-
filter: b =>
446-
b.remote &&
447-
b.getRemoteName() === matchingRemote.name &&
448-
b.getNameWithoutRemote() === pr.headRef?.name,
449-
})
450-
)?.values[0];
451-
if (matchingRemoteBranch == null) continue;
452-
453-
const matchingLocalBranches = (
454-
await repo.getBranches({ filter: b => b.upstream?.name === matchingRemoteBranch.name })
455-
)?.values;
456-
const matchingLocalBranch = matchingLocalBranches?.find(b => b.current) ?? matchingLocalBranches?.[0];
457-
458-
return { repo: repo, remote: matchingRemote, localBranch: matchingLocalBranch };
457+
const remotes = await repo.getRemotes();
458+
for (const remote of remotes) {
459+
if (uniqueRemoteUrls.has(remote.url)) {
460+
repoRemotes.set(remote.url, [repo, remote]);
461+
uniqueRemoteUrls.delete(remote.url);
462+
463+
if (uniqueRemoteUrls.size === 0) return repoRemotes;
464+
} else {
465+
for (const url of uniqueRemoteUrls) {
466+
if (remote.matches(url)) {
467+
repoRemotes.set(url, [repo, remote]);
468+
uniqueRemoteUrls.delete(url);
469+
470+
if (uniqueRemoteUrls.size === 0) return repoRemotes;
471+
472+
break;
473+
}
474+
}
475+
}
476+
}
459477
}
460478

461-
return undefined;
479+
return repoRemotes;
462480
}
463481

464482
async getCategorizedItems(
@@ -495,6 +513,7 @@ export class FocusProvider implements Disposable {
495513
]);
496514

497515
if (cancellation?.isCancellationRequested) throw new CancellationError();
516+
498517
let categorized: FocusItem[] = [];
499518

500519
// TODO: Since this is all repos we probably should order by repos you are a contributor on (or even filter out one you aren't)
@@ -515,6 +534,7 @@ export class FocusProvider implements Disposable {
515534
if (prsWithSuggestionCounts != null) {
516535
const { prs, suggestionCounts } = prsWithSuggestionCounts;
517536
if (prs == null) return categorized;
537+
518538
const filteredPrs = !ignoredRepositories.size
519539
? prs
520540
: prs.filter(
@@ -526,14 +546,17 @@ export class FocusProvider implements Disposable {
526546

527547
const github = await this.container.integrations.get(HostingIntegrationId.GitHub);
528548
const myAccount = await github.getCurrentAccount();
549+
529550
const inputPrs: EnrichablePullRequest[] = filteredPrs.map(pr => {
530551
const providerPr = toProviderPullRequestWithUniqueId(pr.pullRequest);
552+
531553
const enrichable = {
532554
type: 'pr',
533555
id: providerPr.uuid,
534556
url: pr.pullRequest.url,
535557
provider: 'github',
536558
} satisfies EnrichableItem;
559+
537560
const repoIdentity = {
538561
remote: {
539562
url: pr.pullRequest.refs?.head?.url,
@@ -566,6 +589,10 @@ export class FocusProvider implements Disposable {
566589
{ id: myAccount!.username! },
567590
{ enrichedItemsByUniqueId: enrichedItemsByEntityId },
568591
) as FocusPullRequest[];
592+
593+
// Get the unique remote urls
594+
const mappedRemotesPromise = await this.getMatchingRemoteMap(actionableItems);
595+
569596
// Map from shared category label to local actionable category, and get suggested actions
570597
categorized = (await Promise.all(
571598
actionableItems.map(async item => {
@@ -577,7 +604,7 @@ export class FocusProvider implements Disposable {
577604
} else if (codeSuggestionsCount > 0 && item.viewer.isAuthor) {
578605
actionableCategory = 'code-suggestions';
579606
}
580-
const openRepository = await this.getMatchingOpenRepository(item);
607+
const openRepository = await this.getMatchingOpenRepository(item, mappedRemotesPromise);
581608
const suggestedActions = getSuggestedActions(
582609
actionableCategory,
583610
openRepository?.localBranch?.current ?? false,

0 commit comments

Comments
 (0)