@@ -173,6 +173,65 @@ public static async Task<CandidateRepositoryPaths> DetectLocalRepositoryPathAsyn
173
173
}
174
174
}
175
175
176
+ internal readonly struct CandidateFilePath
177
+ {
178
+ public readonly string GitPath ;
179
+ public readonly string BasePath ;
180
+ public readonly string Path ;
181
+
182
+ public CandidateFilePath ( string gitPath , string basePath , string path )
183
+ {
184
+ this . GitPath = gitPath ;
185
+ this . BasePath = basePath ;
186
+ this . Path = path ;
187
+ }
188
+ }
189
+
190
+ #if NET45_OR_GREATER || NETSTANDARD || NETCOREAPP
191
+ public static async ValueTask < CandidateFilePath ? > GetCandidateFilePathAsync (
192
+ #else
193
+ public static async Task < CandidateFilePath ? > GetCandidateFilePathAsync (
194
+ #endif
195
+ Repository repository ,
196
+ string relativePathFromGitPath ,
197
+ CancellationToken ct )
198
+ {
199
+ foreach ( var gitPath in repository . TryingPathList )
200
+ {
201
+ var candidatePath = repository . fileSystem . Combine ( gitPath , relativePathFromGitPath ) ;
202
+ if ( await repository . fileSystem . IsFileExistsAsync ( candidatePath , ct ) )
203
+ {
204
+ return new ( gitPath , repository . fileSystem . GetDirectoryPath ( candidatePath ) , candidatePath ) ;
205
+ }
206
+ }
207
+ return null ;
208
+ }
209
+
210
+ #if NET45_OR_GREATER || NETSTANDARD || NETCOREAPP
211
+ public static async ValueTask < CandidateFilePath [ ] > GetCandidateFilePathsAsync (
212
+ #else
213
+ public static async Task < CandidateFilePath [ ] > GetCandidateFilePathsAsync (
214
+ #endif
215
+ Repository repository ,
216
+ string relativePathFromGitPath ,
217
+ string match ,
218
+ CancellationToken ct ) =>
219
+ ( await Utilities . WhenAll ( repository . TryingPathList .
220
+ #if NET45_OR_GREATER || NETSTANDARD || NETCOREAPP
221
+ Select ( ( Func < string , ValueTask < CandidateFilePath [ ] > > ) ( async gitPath =>
222
+ #else
223
+ Select ( ( async gitPath =>
224
+ #endif
225
+ {
226
+ var basePath = repository . fileSystem . Combine ( gitPath , relativePathFromGitPath ) ;
227
+ var candidatePaths = await repository . fileSystem . GetFilesAsync ( basePath , match , ct ) ;
228
+ return candidatePaths .
229
+ Select ( candidatePath => new CandidateFilePath ( gitPath , basePath , candidatePath ) ) .
230
+ ToArray ( ) ;
231
+ } ) ) ) ) .
232
+ SelectMany ( paths => paths ) .
233
+ ToArray ( ) ;
234
+
176
235
public static string GetReferenceTypeName( ReferenceTypes type ) =>
177
236
type switch
178
237
{
@@ -216,13 +275,12 @@ public static async Task<ReadOnlyDictionary<string, string>> ReadRemoteReference
216
275
Repository repository ,
217
276
CancellationToken ct )
218
277
{
219
- var path = repository . fileSystem . Combine ( repository . GitPath , "config" ) ;
220
- if ( ! await repository . fileSystem . IsFileExistsAsync ( path , ct ) )
278
+ if ( await GetCandidateFilePathAsync ( repository , "config" , ct ) is not { } cp )
221
279
{
222
280
return new ( new ( ) ) ;
223
281
}
224
282
225
- using var fs = await repository . fileSystem . OpenAsync ( path , false , ct ) ;
283
+ using var fs = await repository. fileSystem . OpenAsync ( cp . Path , false , ct ) ;
226
284
var tr = new AsyncTextReader( fs ) ;
227
285
228
286
var remotes = new Dictionary< string , string > ( ) ;
@@ -264,13 +322,12 @@ public static async Task<ReferenceCache> ReadFetchHeadsAsync(
264
322
var remoteNameByUrl = repository. remoteUrls .
265
323
ToDictionary ( entry => entry . Value , entry => entry . Key ) ;
266
324
267
- var path = repository . fileSystem . Combine ( repository . GitPath , "FETCH_HEAD" ) ;
268
- if ( ! await repository . fileSystem . IsFileExistsAsync ( path , ct ) )
325
+ if ( await GetCandidateFilePathAsync ( repository , "FETCH_HEAD" , ct ) is not { } cp )
269
326
{
270
327
return new ( new ( new ( ) ) , new ( new ( ) ) , new ( new ( ) ) ) ;
271
328
}
272
329
273
- using var fs = await repository . fileSystem . OpenAsync ( path , false , ct ) ;
330
+ using var fs = await repository. fileSystem . OpenAsync ( cp . Path , false , ct ) ;
274
331
var tr = new AsyncTextReader( fs ) ;
275
332
276
333
var remoteBranches = new Dictionary< string , Hash > ( ) ;
@@ -356,13 +413,12 @@ public static async Task<ReferenceCache> ReadPackedRefsAsync(
356
413
Repository repository ,
357
414
CancellationToken ct )
358
415
{
359
- var path = repository . fileSystem . Combine ( repository . GitPath , "packed-refs" ) ;
360
- if ( ! await repository . fileSystem . IsFileExistsAsync ( path , ct ) )
416
+ if ( await GetCandidateFilePathAsync ( repository , "packed-refs" , ct ) is not { } cp )
361
417
{
362
418
return new( new ( new ( ) ) , new ( new ( ) ) , new ( new ( ) ) ) ;
363
419
}
364
420
365
- using var fs = await repository . fileSystem . OpenAsync ( path , false , ct ) ;
421
+ using var fs = await repository . fileSystem . OpenAsync ( cp . Path , false , ct ) ;
366
422
var tr = new AsyncTextReader ( fs ) ;
367
423
368
424
var branches = new Dictionary < string , Hash > ( ) ;
@@ -469,10 +525,8 @@ public static async Task<ReferenceCache> ReadPackedRefsAsync(
469
525
Replace ( "refs/tags/" , string . Empty ) ;
470
526
names. Add ( name ) ;
471
527
472
- var path = repository . fileSystem . Combine (
473
- repository . GitPath ,
474
- currentLocation . Replace ( '/' , Path . DirectorySeparatorChar ) ) ;
475
- if ( ! await repository . fileSystem . IsFileExistsAsync ( path , ct ) )
528
+ if ( await GetCandidateFilePathAsync (
529
+ repository , currentLocation . Replace ( '/' , Path . DirectorySeparatorChar ) , ct ) is not { } cp )
476
530
{
477
531
if ( currentLocation . StartsWith ( "refs/heads/" ) )
478
532
{
@@ -498,7 +552,7 @@ public static async Task<ReferenceCache> ReadPackedRefsAsync(
498
552
return null ;
499
553
}
500
554
501
- using var fs = await repository . fileSystem . OpenAsync ( path , false , ct ) ;
555
+ using var fs = await repository. fileSystem . OpenAsync ( cp . Path , false , ct ) ;
502
556
var tr = new AsyncTextReader( fs ) ;
503
557
504
558
var line = await tr. ReadLineAsync ( ct ) ;
@@ -528,14 +582,13 @@ public static Task<PrimitiveReflogEntry[]> ReadReflogEntriesAsync(
528
582
public static async Task < PrimitiveReflogEntry [ ] > ReadReflogEntriesAsync (
529
583
Repository repository , string refRelativePath , CancellationToken ct )
530
584
{
531
- var path = repository . fileSystem . Combine (
532
- repository . GitPath , "logs" , refRelativePath ) ;
533
- if ( ! await repository . fileSystem . IsFileExistsAsync ( path , ct ) )
585
+ if ( await GetCandidateFilePathAsync (
586
+ repository , repository . fileSystem . Combine ( "logs" , refRelativePath ) , ct ) is not { } cp )
534
587
{
535
588
return new PrimitiveReflogEntry [ ] { } ;
536
589
}
537
590
538
- using var fs = await repository . fileSystem . OpenAsync ( path , false , ct ) ;
591
+ using var fs = await repository . fileSystem . OpenAsync ( cp . Path , false , ct ) ;
539
592
var tr = new AsyncTextReader ( fs ) ;
540
593
541
594
var entries = new List < PrimitiveReflogEntry > ( ) ;
@@ -561,37 +614,32 @@ public static async Task<PrimitiveReference[]> ReadReferencesAsync(
561
614
ReferenceTypes type ,
562
615
CancellationToken ct )
563
616
{
564
- var headsPath = repository . fileSystem . Combine (
565
- repository . GitPath , "refs" , GetReferenceTypeName ( type ) ) ;
566
- var files = await repository . fileSystem . GetFilesAsync (
567
- headsPath , "*" , ct ) ;
617
+ var candidatePaths = await GetCandidateFilePathsAsync (
618
+ repository , repository . fileSystem . Combine ( "refs" , GetReferenceTypeName ( type ) ) , "*" , ct ) ;
568
619
var references = ( await Utilities . WhenAll (
569
- files .
620
+ candidatePaths .
570
621
#if NET45_OR_GREATER || NETSTANDARD || NETCOREAPP
571
- Select ( ( Func < string , ValueTask < PrimitiveReference ? > > ) ( async path =>
622
+ Select ( ( Func < CandidateFilePath , ValueTask < PrimitiveReference ? > > ) ( async cp =>
572
623
#else
573
- Select ( async path =>
624
+ Select ( ( async cp =>
574
625
#endif
575
626
{
576
627
if ( await ReadHashAsync (
577
628
repository ,
578
- path . Substring ( repository . GitPath . Length + 1 ) ,
629
+ cp . Path . Substring ( cp . GitPath . Length + 1 ) ,
579
630
ct ) is not { } results )
580
631
{
581
632
return default ( PrimitiveReference ? ) ;
582
633
}
583
634
else
584
635
{
585
636
return new (
586
- path . Substring ( headsPath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
587
- path . Substring ( repository . GitPath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
637
+ cp . Path . Substring ( cp . BasePath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
638
+ cp . Path . Substring ( cp . GitPath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
588
639
results . Hash ) ;
589
640
}
590
641
}
591
- #if NET45_OR_GREATER || NETSTANDARD || NETCOREAPP
592
- )
593
- #endif
594
- ) ) ) .
642
+ ) ) ) ) .
595
643
CollectValue ( reference => reference ) .
596
644
ToDictionary ( reference => reference . Name ) ;
597
645
@@ -632,38 +680,33 @@ public static async Task<PrimitiveTagReference[]> ReadTagReferencesAsync(
632
680
Repository repository ,
633
681
CancellationToken ct )
634
682
{
635
- var headsPath = repository. fileSystem . Combine (
636
- repository . GitPath , "refs" , "tags" ) ;
637
- var files = await repository. fileSystem . GetFilesAsync (
638
- headsPath , "*" , ct ) ;
683
+ var candidatePaths = await GetCandidateFilePathsAsync (
684
+ repository , repository . fileSystem . Combine ( "refs" , "tags" ) , "*" , ct ) ;
639
685
var references = ( await Utilities . WhenAll (
640
- files .
686
+ candidatePaths .
641
687
#if NET45_OR_GREATER || NETSTANDARD || NETCOREAPP
642
- Select ( ( Func < string , ValueTask < PrimitiveTagReference ? > > ) ( async path =>
688
+ Select ( ( Func < CandidateFilePath , ValueTask < PrimitiveTagReference ? > > ) ( async cp =>
643
689
#else
644
- Select ( async path =>
690
+ Select ( ( async cp =>
645
691
#endif
646
692
{
647
693
if ( await ReadHashAsync (
648
694
repository ,
649
- path . Substring ( repository . GitPath . Length + 1 ) ,
695
+ cp . Path . Substring ( cp . GitPath . Length + 1 ) ,
650
696
ct ) is not { } results )
651
697
{
652
698
return default ( PrimitiveTagReference ? ) ;
653
699
}
654
700
else
655
701
{
656
702
return new (
657
- path . Substring ( headsPath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
658
- path . Substring ( repository . GitPath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
703
+ cp . Path . Substring ( cp . BasePath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
704
+ cp . Path . Substring ( cp . GitPath . Length + 1 ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
659
705
results . Hash ,
660
706
null ) ;
661
707
}
662
708
}
663
- #if NET45_OR_GREATER || NETSTANDARD || NETCOREAPP
664
- )
665
- #endif
666
- ) ) ) .
709
+ ) ) ) ) .
667
710
CollectValue ( reference => reference ) .
668
711
ToDictionary ( reference => reference . Name ) ;
669
712
@@ -765,7 +808,6 @@ private static ObjectAccessor GetObjectAccessor(
765
808
}
766
809
}
767
810
768
-
769
811
public static async Task < PrimitiveCommit ? > ReadCommitAsync (
770
812
Repository repository ,
771
813
Hash hash , CancellationToken ct )
0 commit comments