@@ -1115,16 +1115,59 @@ static int add_patterns(const char *fname, const char *base, int baselen,
1115
1115
size_t size = 0 ;
1116
1116
char * buf ;
1117
1117
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 );
1126
1157
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 ) {
1128
1171
if (!istate )
1129
1172
return -1 ;
1130
1173
r = read_skip_worktree_file_from_index (istate , fname ,
0 commit comments