@@ -41,6 +41,7 @@ static struct trace_key trace_fscache = TRACE_KEY_INIT(FSCACHE);
4141struct fsentry {
4242 struct hashmap_entry ent ;
4343 mode_t st_mode ;
44+ ULONG reparse_tag ;
4445 /* Length of name. */
4546 unsigned short len ;
4647 /*
@@ -180,6 +181,10 @@ static struct fsentry *fseentry_create_entry(struct fscache *cache, struct fsent
180181
181182 fse = fsentry_alloc (cache , list , buf , len );
182183
184+ fse -> reparse_tag =
185+ fdata -> FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ?
186+ fdata -> EaSize : 0 ;
187+
183188 /*
184189 * On certain Windows versions, host directories mapped into
185190 * Windows Containers ("Volumes", see https://docs.docker.com/storage/volumes/)
@@ -189,8 +194,7 @@ static struct fsentry *fseentry_create_entry(struct fscache *cache, struct fsent
189194 * Let's work around this by detecting that situation and
190195 * telling Git that these are *not* symbolic links.
191196 */
192- if (fdata -> FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
193- fdata -> EaSize == IO_REPARSE_TAG_SYMLINK &&
197+ if (fse -> reparse_tag == IO_REPARSE_TAG_SYMLINK &&
194198 sizeof (buf ) > (list ? list -> len + 1 : 0 ) + fse -> len + 1 &&
195199 is_inside_windows_container ()) {
196200 size_t off = 0 ;
@@ -461,6 +465,7 @@ int fscache_enable(size_t initial_size)
461465 /* redirect opendir and lstat to the fscache implementations */
462466 opendir = fscache_opendir ;
463467 lstat = fscache_lstat ;
468+ win32_is_mount_point = fscache_is_mount_point ;
464469 }
465470 initialized ++ ;
466471 LeaveCriticalSection (& fscache_cs );
@@ -521,6 +526,7 @@ void fscache_disable(void)
521526 /* reset opendir and lstat to the original implementations */
522527 opendir = dirent_opendir ;
523528 lstat = mingw_lstat ;
529+ win32_is_mount_point = mingw_is_mount_point ;
524530 }
525531 LeaveCriticalSection (& fscache_cs );
526532
@@ -588,6 +594,38 @@ int fscache_lstat(const char *filename, struct stat *st)
588594 return 0 ;
589595}
590596
597+ /*
598+ * is_mount_point() replacement, uses cache if enabled, otherwise falls
599+ * back to mingw_is_mount_point().
600+ */
601+ int fscache_is_mount_point (struct strbuf * path )
602+ {
603+ int dirlen , base , len ;
604+ struct fsentry key [2 ], * fse ;
605+ struct fscache * cache = fscache_getcache ();
606+
607+ if (!cache || !do_fscache_enabled (cache , path -> buf ))
608+ return mingw_is_mount_point (path );
609+
610+ cache -> lstat_requests ++ ;
611+ /* split path into path + name */
612+ len = path -> len ;
613+ if (len && is_dir_sep (path -> buf [len - 1 ]))
614+ len -- ;
615+ base = len ;
616+ while (base && !is_dir_sep (path -> buf [base - 1 ]))
617+ base -- ;
618+ dirlen = base ? base - 1 : 0 ;
619+
620+ /* lookup entry for path + name in cache */
621+ fsentry_init (key , NULL , path -> buf , dirlen );
622+ fsentry_init (key + 1 , key , path -> buf + base , len - base );
623+ fse = fscache_get (cache , key + 1 );
624+ if (!fse )
625+ return mingw_is_mount_point (path );
626+ return fse -> reparse_tag == IO_REPARSE_TAG_MOUNT_POINT ;
627+ }
628+
591629typedef struct fscache_DIR {
592630 struct DIR base_dir ; /* extend base struct DIR */
593631 struct fsentry * pfsentry ;
0 commit comments