@@ -73,80 +73,89 @@ export class StashGitSubProvider implements GitStashSubProvider {
7373 ) : Promise < GitStash | undefined > {
7474 if ( repoPath == null ) return undefined ;
7575
76- let stash = this . cache . stashes ?. get ( repoPath ) ;
77- if ( stash == null ) {
78- const parser = getStashLogParser ( ) ;
79- const args = [ ...parser . arguments ] ;
76+ let stashPromise = this . cache . stashes ?. get ( repoPath ) ;
77+ if ( stashPromise == null ) {
78+ async function load ( this : StashGitSubProvider ) : Promise < GitStash > {
79+ const parser = getStashLogParser ( ) ;
80+ const args = [ ...parser . arguments ] ;
81+
82+ const similarityThreshold = configuration . get ( 'advanced.similarityThreshold' ) ;
83+ args . push ( `-M${ similarityThreshold == null ? '' : `${ similarityThreshold } %` } ` ) ;
84+
85+ const result = await this . git . exec (
86+ { cwd : repoPath , cancellation : cancellation } ,
87+ 'stash' ,
88+ 'list' ,
89+ ...args ,
90+ ) ;
91+
92+ const stashes = new Map < string , GitStashCommit > ( ) ;
93+
94+ for ( const s of parser . parse ( result . stdout ) ) {
95+ stashes . set ( s . sha , createStash ( this . container , s , repoPath ) ) ;
96+ }
8097
81- const similarityThreshold = configuration . get ( 'advanced.similarityThreshold' ) ;
82- args . push ( `-M ${ similarityThreshold == null ? '' : ` ${ similarityThreshold } %` } ` ) ;
98+ return { repoPath : repoPath , stashes : stashes } ;
99+ }
83100
84- const result = await this . git . exec ( { cwd : repoPath , cancellation : cancellation } , 'stash' , 'list' , ...args ) ;
101+ stashPromise = load . call ( this ) ;
102+ this . cache . stashes ?. set ( repoPath , stashPromise ) ;
103+ }
85104
86- const stashes = new Map < string , GitStashCommit > ( ) ;
105+ const stash = await stashPromise ;
106+ if ( ! options ?. reachableFrom || ! stash ?. stashes . size ) return stash ;
87107
88- for ( const s of parser . parse ( result . stdout ) ) {
89- stashes . set ( s . sha , createStash ( this . container , s , repoPath ) ) ;
90- }
108+ // Return only reachable stashes from the given ref
109+ // Create a copy because we are going to modify it and we don't want to mutate the cache
110+ const stashes = new Map ( stash . stashes ) ;
91111
92- stash = { repoPath : repoPath , stashes : stashes } ;
112+ const oldestStashDate = new Date ( min ( stash . stashes . values ( ) , c => c . date . getTime ( ) ) ) . toISOString ( ) ;
93113
94- this . cache . stashes ?. set ( repoPath , stash ) ;
95- }
114+ const result = await this . git . exec (
115+ { cwd : repoPath , cancellation : cancellation , errors : GitErrorHandling . Ignore } ,
116+ 'rev-list' ,
117+ `--since="${ oldestStashDate } "` ,
118+ '--date-order' ,
119+ options . reachableFrom ,
120+ '--' ,
121+ ) ;
96122
97- // Return only reachable stashes from the given ref
98- if ( options ?. reachableFrom && stash ?. stashes . size ) {
99- // Create a copy because we are going to modify it and we don't want to mutate the cache
100- stash = { ...stash , stashes : new Map ( stash . stashes ) } ;
101-
102- const oldestStashDate = new Date ( min ( stash . stashes . values ( ) , c => c . date . getTime ( ) ) ) . toISOString ( ) ;
103-
104- const result = await this . git . exec (
105- { cwd : repoPath , cancellation : cancellation , errors : GitErrorHandling . Ignore } ,
106- 'rev-list' ,
107- `--since="${ oldestStashDate } "` ,
108- '--date-order' ,
109- options . reachableFrom ,
110- '--' ,
111- ) ;
123+ const ancestors = result . stdout . trim ( ) . split ( '\n' ) ;
124+ const reachableCommits =
125+ ancestors ?. length && ( ancestors . length !== 1 || ancestors [ 0 ] ) ? new Set ( ancestors ) : undefined ;
126+ if ( reachableCommits ?. size ) {
127+ const reachableStashes = new Set < string > ( ) ;
112128
113- const ancestors = result . stdout . trim ( ) . split ( '\n' ) ;
114- const reachableCommits =
115- ancestors ?. length && ( ancestors . length !== 1 || ancestors [ 0 ] ) ? new Set ( ancestors ) : undefined ;
116- if ( reachableCommits ?. size ) {
117- const reachableStashes = new Set < string > ( ) ;
129+ // First pass: mark directly reachable stashes
130+ for ( const [ sha , s ] of stash . stashes ) {
131+ if ( s . parents . some ( p => p === options . reachableFrom || reachableCommits . has ( p ) ) ) {
132+ reachableStashes . add ( sha ) ;
133+ }
134+ }
118135
119- // First pass: mark directly reachable stashes
136+ // Second pass: mark stashes that build upon reachable stashes
137+ let changed ;
138+ do {
139+ changed = false ;
120140 for ( const [ sha , s ] of stash . stashes ) {
121- if ( s . parents . some ( p => p === options . reachableFrom || reachableCommits . has ( p ) ) ) {
141+ if ( ! reachableStashes . has ( sha ) && s . parents . some ( p => reachableStashes . has ( p ) ) ) {
122142 reachableStashes . add ( sha ) ;
143+ changed = true ;
123144 }
124145 }
146+ } while ( changed ) ;
125147
126- // Second pass: mark stashes that build upon reachable stashes
127- let changed ;
128- do {
129- changed = false ;
130- for ( const [ sha , s ] of stash . stashes ) {
131- if ( ! reachableStashes . has ( sha ) && s . parents . some ( p => reachableStashes . has ( p ) ) ) {
132- reachableStashes . add ( sha ) ;
133- changed = true ;
134- }
135- }
136- } while ( changed ) ;
137-
138- // Remove unreachable stashes
139- for ( const [ sha ] of stash . stashes ) {
140- if ( ! reachableStashes . has ( sha ) ) {
141- stash . stashes . delete ( sha ) ;
142- }
148+ // Remove unreachable stashes
149+ for ( const [ sha ] of stash . stashes ) {
150+ if ( ! reachableStashes . has ( sha ) ) {
151+ stashes . delete ( sha ) ;
143152 }
144- } else {
145- stash . stashes . clear ( ) ;
146153 }
154+ } else {
155+ stashes . clear ( ) ;
147156 }
148157
149- return stash ;
158+ return { ... stash , stashes : stashes } ;
150159 }
151160
152161 @log ( )
@@ -342,7 +351,7 @@ export class StashGitSubProvider implements GitStashSubProvider {
342351 }
343352}
344353
345- export function convertStashesToStdin ( stashOrStashes : GitStash | Map < string , GitStashCommit > | undefined ) : {
354+ export function convertStashesToStdin ( stashOrStashes : GitStash | ReadonlyMap < string , GitStashCommit > | undefined ) : {
346355 readonly stdin : string | undefined ;
347356 readonly stashes : Map < string , GitStashCommit > ;
348357 readonly remappedIds : Map < string , string > ;
@@ -351,40 +360,23 @@ export function convertStashesToStdin(stashOrStashes: GitStash | Map<string, Git
351360 if ( stashOrStashes == null ) return { stdin : undefined , stashes : new Map ( ) , remappedIds : remappedIds } ;
352361
353362 let stdin : string | undefined ;
354- let stashes : Map < string , GitStashCommit > ;
355-
356- if ( 'stashes' in stashOrStashes ) {
357- stashes = new Map ( stashOrStashes . stashes ) ;
358- if ( stashOrStashes . stashes . size ) {
359- stdin = '' ;
360- for ( const stash of stashOrStashes . stashes . values ( ) ) {
361- stdin += ` ${ stash . sha . substring ( 0 , 9 ) } \n` ;
362- // Include the stash's 2nd (index files) and 3rd (untracked files) parents
363- for ( const p of skip ( stash . parents , 1 ) ) {
364- remappedIds . set ( p , stash . sha ) ;
365-
363+ const original = ' stashes' in stashOrStashes ? stashOrStashes . stashes : stashOrStashes ;
364+ const stashes = new Map < string , GitStashCommit > ( original ) ;
365+
366+ if ( original . size ) {
367+ stdin = '' ;
368+ for ( const stash of original . values ( ) ) {
369+ stdin += ` ${ stash . sha . substring ( 0 , 9 ) } \n` ;
370+ // Include the stash's 2nd (index files) and 3rd (untracked files) parents (if they aren't already in the map)
371+ for ( const p of skip ( stash . parents , 1 ) ) {
372+ remappedIds . set ( p , stash . sha ) ;
373+
374+ if ( ! stashes . has ( p ) ) {
366375 stashes . set ( p , stash ) ;
367376 stdin += `${ p . substring ( 0 , 9 ) } \n` ;
368377 }
369378 }
370379 }
371- } else {
372- if ( stashOrStashes . size ) {
373- stdin = '' ;
374- for ( const stash of stashOrStashes . values ( ) ) {
375- stdin += `${ stash . sha . substring ( 0 , 9 ) } \n` ;
376- // Include the stash's 2nd (index files) and 3rd (untracked files) parents (if they aren't already in the map)
377- for ( const p of skip ( stash . parents , 1 ) ) {
378- remappedIds . set ( p , stash . sha ) ;
379-
380- if ( ! stashOrStashes . has ( p ) ) {
381- stashOrStashes . set ( p , stash ) ;
382- stdin += `${ p . substring ( 0 , 9 ) } \n` ;
383- }
384- }
385- }
386- }
387- stashes = stashOrStashes ;
388380 }
389381
390382 return { stdin : stdin || undefined , stashes : stashes , remappedIds : remappedIds } ;
0 commit comments