@@ -1115,16 +1115,59 @@ static int add_patterns(const char *fname, const char *base, int baselen,
11151115 size_t size = 0 ;
11161116 char * buf ;
11171117
1118- if (flags & PATTERN_NOFOLLOW )
1119- fd = open_nofollow (fname , O_RDONLY );
1120- else
1121- fd = open (fname , O_RDONLY );
1122-
1123- if (fd < 0 || fstat (fd , & st ) < 0 ) {
1124- if (fd < 0 )
1125- warn_on_fopen_errors (fname );
1118+ /*
1119+ * A performance optimization for status.
1120+ *
1121+ * During a status scan, git looks in each directory for a .gitignore
1122+ * file before scanning the directory. Since .gitignore files are not
1123+ * that common, we can waste a lot of time looking for files that are
1124+ * not there. Fortunately, the fscache already knows if the directory
1125+ * contains a .gitignore file, since it has already read the directory
1126+ * and it already has the stat-data.
1127+ *
1128+ * If the fscache is enabled, use the fscache-lstat() interlude to see
1129+ * if the file exists (in the fscache hash maps) before trying to open()
1130+ * it.
1131+ *
1132+ * This causes problem when the .gitignore file is a symlink, because
1133+ * we call lstat() rather than stat() on the symlnk and the resulting
1134+ * stat-data is for the symlink itself rather than the target file.
1135+ * We CANNOT use stat() here because the fscache DOES NOT install an
1136+ * interlude for stat() and mingw_stat() always calls "open-fstat-close"
1137+ * on the file and defeats the purpose of the optimization here. Since
1138+ * symlinks are even more rare than .gitignore files, we force a fstat()
1139+ * after our open() to get stat-data for the target file.
1140+ */
1141+ if (is_fscache_enabled (fname )) {
1142+ if (lstat (fname , & st ) < 0 ) {
1143+ fd = -1 ;
1144+ } else {
1145+ fd = open (fname , O_RDONLY );
1146+ if (fd < 0 )
1147+ warn_on_fopen_errors (fname );
1148+ else if (S_ISLNK (st .st_mode ) && fstat (fd , & st ) < 0 ) {
1149+ warn_on_fopen_errors (fname );
1150+ close (fd );
1151+ fd = -1 ;
1152+ }
1153+ }
1154+ } else {
1155+ if (flags & PATTERN_NOFOLLOW )
1156+ fd = open_nofollow (fname , O_RDONLY );
11261157 else
1127- close (fd );
1158+ fd = open (fname , O_RDONLY );
1159+
1160+ if (fd < 0 || fstat (fd , & st ) < 0 ) {
1161+ if (fd < 0 )
1162+ warn_on_fopen_errors (fname );
1163+ else {
1164+ close (fd );
1165+ fd = -1 ;
1166+ }
1167+ }
1168+ }
1169+
1170+ if (fd < 0 ) {
11281171 if (!istate )
11291172 return -1 ;
11301173 r = read_skip_worktree_file_from_index (istate , fname ,
0 commit comments