@@ -1079,16 +1079,59 @@ static int add_patterns(const char *fname, const char *base, int baselen,
1079
1079
size_t size = 0 ;
1080
1080
char * buf ;
1081
1081
1082
- if (flags & PATTERN_NOFOLLOW )
1083
- fd = open_nofollow (fname , O_RDONLY );
1084
- else
1085
- fd = open (fname , O_RDONLY );
1086
-
1087
- if (fd < 0 || fstat (fd , & st ) < 0 ) {
1088
- if (fd < 0 )
1089
- warn_on_fopen_errors (fname );
1082
+ /*
1083
+ * A performance optimization for status.
1084
+ *
1085
+ * During a status scan, git looks in each directory for a .gitignore
1086
+ * file before scanning the directory. Since .gitignore files are not
1087
+ * that common, we can waste a lot of time looking for files that are
1088
+ * not there. Fortunately, the fscache already knows if the directory
1089
+ * contains a .gitignore file, since it has already read the directory
1090
+ * and it already has the stat-data.
1091
+ *
1092
+ * If the fscache is enabled, use the fscache-lstat() interlude to see
1093
+ * if the file exists (in the fscache hash maps) before trying to open()
1094
+ * it.
1095
+ *
1096
+ * This causes problem when the .gitignore file is a symlink, because
1097
+ * we call lstat() rather than stat() on the symlnk and the resulting
1098
+ * stat-data is for the symlink itself rather than the target file.
1099
+ * We CANNOT use stat() here because the fscache DOES NOT install an
1100
+ * interlude for stat() and mingw_stat() always calls "open-fstat-close"
1101
+ * on the file and defeats the purpose of the optimization here. Since
1102
+ * symlinks are even more rare than .gitignore files, we force a fstat()
1103
+ * after our open() to get stat-data for the target file.
1104
+ */
1105
+ if (is_fscache_enabled (fname )) {
1106
+ if (lstat (fname , & st ) < 0 ) {
1107
+ fd = -1 ;
1108
+ } else {
1109
+ fd = open (fname , O_RDONLY );
1110
+ if (fd < 0 )
1111
+ warn_on_fopen_errors (fname );
1112
+ else if (S_ISLNK (st .st_mode ) && fstat (fd , & st ) < 0 ) {
1113
+ warn_on_fopen_errors (fname );
1114
+ close (fd );
1115
+ fd = -1 ;
1116
+ }
1117
+ }
1118
+ } else {
1119
+ if (flags & PATTERN_NOFOLLOW )
1120
+ fd = open_nofollow (fname , O_RDONLY );
1090
1121
else
1091
- close (fd );
1122
+ fd = open (fname , O_RDONLY );
1123
+
1124
+ if (fd < 0 || fstat (fd , & st ) < 0 ) {
1125
+ if (fd < 0 )
1126
+ warn_on_fopen_errors (fname );
1127
+ else {
1128
+ close (fd );
1129
+ fd = -1 ;
1130
+ }
1131
+ }
1132
+ }
1133
+
1134
+ if (fd < 0 ) {
1092
1135
if (!istate )
1093
1136
return -1 ;
1094
1137
r = read_skip_worktree_file_from_index (istate , fname ,
0 commit comments