@@ -407,7 +407,7 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
407
407
/// Type that abstracts over [`gix::dir::entry::Kind`] and [`fs::FileType`].
408
408
#[ derive( Debug , Clone , Copy ) ]
409
409
enum FileType {
410
- File ,
410
+ File { maybe_symlink : bool } ,
411
411
Dir ,
412
412
Symlink ,
413
413
Other ,
@@ -416,7 +416,9 @@ enum FileType {
416
416
impl From < fs:: FileType > for FileType {
417
417
fn from ( value : fs:: FileType ) -> Self {
418
418
if value. is_file ( ) {
419
- FileType :: File
419
+ FileType :: File {
420
+ maybe_symlink : false ,
421
+ }
420
422
} else if value. is_dir ( ) {
421
423
FileType :: Dir
422
424
} else if value. is_symlink ( ) {
@@ -432,7 +434,9 @@ impl From<gix::dir::entry::Kind> for FileType {
432
434
use gix:: dir:: entry:: Kind ;
433
435
match value {
434
436
Kind :: Untrackable => FileType :: Other ,
435
- Kind :: File => FileType :: File ,
437
+ Kind :: File => FileType :: File {
438
+ maybe_symlink : false ,
439
+ } ,
436
440
Kind :: Symlink => FileType :: Symlink ,
437
441
Kind :: Directory | Kind :: Repository => FileType :: Dir ,
438
442
}
@@ -454,7 +458,7 @@ impl PathEntry {
454
458
/// Similar to [`std::path::Path::is_file`]
455
459
/// but doesn't follow the symbolic link nor make any system call
456
460
pub fn is_file ( & self ) -> bool {
457
- matches ! ( self . ty, FileType :: File )
461
+ matches ! ( self . ty, FileType :: File { .. } )
458
462
}
459
463
460
464
/// Similar to [`std::path::Path::is_dir`]
@@ -468,6 +472,19 @@ impl PathEntry {
468
472
pub fn is_symlink ( & self ) -> bool {
469
473
matches ! ( self . ty, FileType :: Symlink )
470
474
}
475
+
476
+ /// Whether this path might be a plain text symlink.
477
+ ///
478
+ /// Git may check out symlinks as plain text files that contain the link texts,
479
+ /// when either `core.symlinks` is `false`, or on Windows.
480
+ pub fn maybe_plain_text_symlink ( & self ) -> bool {
481
+ matches ! (
482
+ self . ty,
483
+ FileType :: File {
484
+ maybe_symlink: true
485
+ }
486
+ )
487
+ }
471
488
}
472
489
473
490
impl std:: ops:: Deref for PathEntry {
@@ -713,7 +730,24 @@ fn list_files_gix(
713
730
&& item. entry . rela_path == "Cargo.lock" )
714
731
} )
715
732
} )
716
- . map ( |res| res. map ( |item| ( item. entry . rela_path , item. entry . disk_kind ) ) )
733
+ . map ( |res| {
734
+ res. map ( |item| {
735
+ // Assumption: if a file tracked as a symlink in Git index, and
736
+ // the actual file type on disk is file, then it might be a
737
+ // plain text file symlink.
738
+ // There are exceptions like the file has changed from a symlink
739
+ // to a real text file, but hasn't been committed to Git index.
740
+ // Exceptions may be rare so we're okay with this now.
741
+ let maybe_plain_text_symlink = item. entry . index_kind
742
+ == Some ( gix:: dir:: entry:: Kind :: Symlink )
743
+ && item. entry . disk_kind == Some ( gix:: dir:: entry:: Kind :: File ) ;
744
+ (
745
+ item. entry . rela_path ,
746
+ item. entry . disk_kind ,
747
+ maybe_plain_text_symlink,
748
+ )
749
+ } )
750
+ } )
717
751
. chain (
718
752
// Append entries that might be tracked in `<pkg_root>/target/`.
719
753
index
@@ -731,12 +765,13 @@ fn list_files_gix(
731
765
// This traversal is not part of a `status()`, and tracking things in `target/`
732
766
// is rare.
733
767
None ,
768
+ false ,
734
769
)
735
770
} )
736
771
. map ( Ok ) ,
737
772
)
738
773
{
739
- let ( rela_path, kind) = item?;
774
+ let ( rela_path, kind, maybe_plain_text_symlink ) = item?;
740
775
let file_path = root. join ( gix:: path:: from_bstr ( rela_path) ) ;
741
776
if file_path. file_name ( ) . and_then ( |name| name. to_str ( ) ) == Some ( "Cargo.toml" ) {
742
777
// Keep track of all sub-packages found and also strip out all
@@ -781,9 +816,16 @@ fn list_files_gix(
781
816
} else if ( filter) ( & file_path, is_dir) {
782
817
assert ! ( !is_dir) ;
783
818
trace ! ( " found {}" , file_path. display( ) ) ;
819
+ let ty = match kind. map ( Into :: into) {
820
+ Some ( FileType :: File { .. } ) => FileType :: File {
821
+ maybe_symlink : maybe_plain_text_symlink,
822
+ } ,
823
+ Some ( ty) => ty,
824
+ None => FileType :: Other ,
825
+ } ;
784
826
files. push ( PathEntry {
785
827
path : file_path,
786
- ty : kind . map ( Into :: into ) . unwrap_or ( FileType :: Other ) ,
828
+ ty,
787
829
} ) ;
788
830
}
789
831
}
0 commit comments