@@ -298,6 +298,61 @@ async function spawnGitAsync(
298
298
return stdout ;
299
299
}
300
300
301
+ function isIterable < T > ( value : Iterable < T > | AsyncIterable < T > ) : value is Iterable < T > {
302
+ return Symbol . iterator in value ;
303
+ }
304
+
305
+ /**
306
+ * Uses `git hash-object` to hash the provided files. Unlike `getGitHashForFiles`, this API is asynchronous, and also allows for
307
+ * the input file paths to be specified as an async iterable.
308
+ *
309
+ * @param rootDirectory - The root directory to which paths are specified relative. Must be the root of the Git repository.
310
+ * @param filesToHash - The file paths to hash using `git hash-object`
311
+ * @param gitPath - The path to the Git executable
312
+ * @returns An iterable of [filePath, hash] pairs
313
+ *
314
+ * @remarks
315
+ * The input file paths must be specified relative to the Git repository root, or else be absolute paths.
316
+ * @beta
317
+ */
318
+ export async function hashFilesAsync (
319
+ rootDirectory : string ,
320
+ filesToHash : Iterable < string > | AsyncIterable < string > ,
321
+ gitPath ?: string
322
+ ) : Promise < Iterable < [ string , string ] > > {
323
+ const hashPaths : string [ ] = [ ] ;
324
+
325
+ const input : Readable = Readable . from (
326
+ isIterable ( filesToHash )
327
+ ? ( function * ( ) : IterableIterator < string > {
328
+ for ( const file of filesToHash ) {
329
+ hashPaths . push ( file ) ;
330
+ yield `${ file } \n` ;
331
+ }
332
+ } ) ( )
333
+ : ( async function * ( ) : AsyncIterableIterator < string > {
334
+ for await ( const file of filesToHash ) {
335
+ hashPaths . push ( file ) ;
336
+ yield `${ file } \n` ;
337
+ }
338
+ } ) ( ) ,
339
+ {
340
+ encoding : 'utf-8' ,
341
+ objectMode : false ,
342
+ autoDestroy : true
343
+ }
344
+ ) ;
345
+
346
+ const hashObjectResult : string = await spawnGitAsync (
347
+ gitPath ,
348
+ STANDARD_GIT_OPTIONS . concat ( [ 'hash-object' , '--stdin-paths' ] ) ,
349
+ rootDirectory ,
350
+ input
351
+ ) ;
352
+
353
+ return parseGitHashObject ( hashObjectResult , hashPaths ) ;
354
+ }
355
+
301
356
/**
302
357
* Gets the object hashes for all files in the Git repo, combining the current commit with working tree state.
303
358
* Uses async operations and runs all primary Git calls in parallel.
@@ -346,46 +401,34 @@ export async function getRepoStateAsync(
346
401
rootDirectory
347
402
) . then ( parseGitStatus ) ;
348
403
349
- const hashPaths : string [ ] = [ ] ;
350
404
async function * getFilesToHash ( ) : AsyncIterableIterator < string > {
351
405
if ( additionalRelativePathsToHash ) {
352
406
for ( const file of additionalRelativePathsToHash ) {
353
- hashPaths . push ( file ) ;
354
- yield `${ file } \n` ;
407
+ yield file ;
355
408
}
356
409
}
357
410
358
411
const [ { files } , locallyModified ] = await Promise . all ( [ statePromise , locallyModifiedPromise ] ) ;
359
412
360
413
for ( const [ filePath , exists ] of locallyModified ) {
361
414
if ( exists ) {
362
- hashPaths . push ( filePath ) ;
363
- yield `${ filePath } \n` ;
415
+ yield filePath ;
364
416
} else {
365
417
files . delete ( filePath ) ;
366
418
}
367
419
}
368
420
}
369
421
370
- const hashObjectPromise : Promise < string > = spawnGitAsync (
371
- gitPath ,
372
- STANDARD_GIT_OPTIONS . concat ( [ 'hash-object' , '--stdin-paths' ] ) ,
422
+ const hashObjectPromise : Promise < Iterable < [ string , string ] > > = hashFilesAsync (
373
423
rootDirectory ,
374
- Readable . from ( getFilesToHash ( ) , {
375
- encoding : 'utf-8' ,
376
- objectMode : false ,
377
- autoDestroy : true
378
- } )
424
+ getFilesToHash ( ) ,
425
+ gitPath
379
426
) ;
380
427
381
- const [ { files, submodules } , hashObject ] = await Promise . all ( [
382
- statePromise ,
383
- hashObjectPromise ,
384
- locallyModifiedPromise
385
- ] ) ;
428
+ const [ { files, submodules } ] = await Promise . all ( [ statePromise , locallyModifiedPromise ] ) ;
386
429
387
430
// The result of "git hash-object" will be a list of file hashes delimited by newlines
388
- for ( const [ filePath , hash ] of parseGitHashObject ( hashObject , hashPaths ) ) {
431
+ for ( const [ filePath , hash ] of await hashObjectPromise ) {
389
432
files . set ( filePath , hash ) ;
390
433
}
391
434
0 commit comments