@@ -7,13 +7,13 @@ import { CancellationError } from '../../errors';
77import { openComparisonChanges } from '../../git/actions/commit' ;
88import type { Account } from '../../git/models/author' ;
99import type { GitBranch } from '../../git/models/branch' ;
10+ import { getLocalBranchByUpstream } from '../../git/models/branch' ;
1011import type { SearchedIssue } from '../../git/models/issue' ;
1112import type { SearchedPullRequest } from '../../git/models/pullRequest' ;
1213import { getComparisonRefsForPullRequest } from '../../git/models/pullRequest' ;
1314import type { GitRemote } from '../../git/models/remote' ;
1415import type { Repository } from '../../git/models/repository' ;
1516import type { CodeSuggestionCounts , Draft } from '../../gk/models/drafts' ;
16- import { getPathFromProviderIdentity } from '../../gk/models/repositoryIdentities' ;
1717import { executeCommand , registerCommand } from '../../system/command' ;
1818import { configuration } from '../../system/configuration' ;
1919import { 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