@@ -7,13 +7,13 @@ import { CancellationError } from '../../errors';
7
7
import { openComparisonChanges } from '../../git/actions/commit' ;
8
8
import type { Account } from '../../git/models/author' ;
9
9
import type { GitBranch } from '../../git/models/branch' ;
10
+ import { getLocalBranchByUpstream } from '../../git/models/branch' ;
10
11
import type { SearchedIssue } from '../../git/models/issue' ;
11
12
import type { SearchedPullRequest } from '../../git/models/pullRequest' ;
12
13
import { getComparisonRefsForPullRequest } from '../../git/models/pullRequest' ;
13
14
import type { GitRemote } from '../../git/models/remote' ;
14
15
import type { Repository } from '../../git/models/repository' ;
15
16
import type { CodeSuggestionCounts , Draft } from '../../gk/models/drafts' ;
16
- import { getPathFromProviderIdentity } from '../../gk/models/repositoryIdentities' ;
17
17
import { executeCommand , registerCommand } from '../../system/command' ;
18
18
import { configuration } from '../../system/configuration' ;
19
19
import { getSettledValue } from '../../system/promise' ;
@@ -426,39 +426,57 @@ export class FocusProvider implements Disposable {
426
426
) ;
427
427
}
428
428
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
+
430
456
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
+ }
459
477
}
460
478
461
- return undefined ;
479
+ return repoRemotes ;
462
480
}
463
481
464
482
async getCategorizedItems (
@@ -495,6 +513,7 @@ export class FocusProvider implements Disposable {
495
513
] ) ;
496
514
497
515
if ( cancellation ?. isCancellationRequested ) throw new CancellationError ( ) ;
516
+
498
517
let categorized : FocusItem [ ] = [ ] ;
499
518
500
519
// 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 {
515
534
if ( prsWithSuggestionCounts != null ) {
516
535
const { prs, suggestionCounts } = prsWithSuggestionCounts ;
517
536
if ( prs == null ) return categorized ;
537
+
518
538
const filteredPrs = ! ignoredRepositories . size
519
539
? prs
520
540
: prs . filter (
@@ -526,14 +546,17 @@ export class FocusProvider implements Disposable {
526
546
527
547
const github = await this . container . integrations . get ( HostingIntegrationId . GitHub ) ;
528
548
const myAccount = await github . getCurrentAccount ( ) ;
549
+
529
550
const inputPrs : EnrichablePullRequest [ ] = filteredPrs . map ( pr => {
530
551
const providerPr = toProviderPullRequestWithUniqueId ( pr . pullRequest ) ;
552
+
531
553
const enrichable = {
532
554
type : 'pr' ,
533
555
id : providerPr . uuid ,
534
556
url : pr . pullRequest . url ,
535
557
provider : 'github' ,
536
558
} satisfies EnrichableItem ;
559
+
537
560
const repoIdentity = {
538
561
remote : {
539
562
url : pr . pullRequest . refs ?. head ?. url ,
@@ -566,6 +589,10 @@ export class FocusProvider implements Disposable {
566
589
{ id : myAccount ! . username ! } ,
567
590
{ enrichedItemsByUniqueId : enrichedItemsByEntityId } ,
568
591
) as FocusPullRequest [ ] ;
592
+
593
+ // Get the unique remote urls
594
+ const mappedRemotesPromise = await this . getMatchingRemoteMap ( actionableItems ) ;
595
+
569
596
// Map from shared category label to local actionable category, and get suggested actions
570
597
categorized = ( await Promise . all (
571
598
actionableItems . map ( async item => {
@@ -577,7 +604,7 @@ export class FocusProvider implements Disposable {
577
604
} else if ( codeSuggestionsCount > 0 && item . viewer . isAuthor ) {
578
605
actionableCategory = 'code-suggestions' ;
579
606
}
580
- const openRepository = await this . getMatchingOpenRepository ( item ) ;
607
+ const openRepository = await this . getMatchingOpenRepository ( item , mappedRemotesPromise ) ;
581
608
const suggestedActions = getSuggestedActions (
582
609
actionableCategory ,
583
610
openRepository ?. localBranch ?. current ?? false ,
0 commit comments