@@ -1054,12 +1054,55 @@ static int add_patterns(const char *fname, const char *base, int baselen,
1054
1054
size_t size = 0 ;
1055
1055
char * buf ;
1056
1056
1057
- fd = open (fname , O_RDONLY );
1058
- if (fd < 0 || fstat (fd , & st ) < 0 ) {
1059
- if (fd < 0 )
1060
- warn_on_fopen_errors (fname );
1061
- else
1062
- close (fd );
1057
+ /*
1058
+ * A performance optimization for status.
1059
+ *
1060
+ * During a status scan, git looks in each directory for a .gitignore
1061
+ * file before scanning the directory. Since .gitignore files are not
1062
+ * that common, we can waste a lot of time looking for files that are
1063
+ * not there. Fortunately, the fscache already knows if the directory
1064
+ * contains a .gitignore file, since it has already read the directory
1065
+ * and it already has the stat-data.
1066
+ *
1067
+ * If the fscache is enabled, use the fscache-lstat() interlude to see
1068
+ * if the file exists (in the fscache hash maps) before trying to open()
1069
+ * it.
1070
+ *
1071
+ * This causes problem when the .gitignore file is a symlink, because
1072
+ * we call lstat() rather than stat() on the symlnk and the resulting
1073
+ * stat-data is for the symlink itself rather than the target file.
1074
+ * We CANNOT use stat() here because the fscache DOES NOT install an
1075
+ * interlude for stat() and mingw_stat() always calls "open-fstat-close"
1076
+ * on the file and defeats the purpose of the optimization here. Since
1077
+ * symlinks are even more rare than .gitignore files, we force a fstat()
1078
+ * after our open() to get stat-data for the target file.
1079
+ */
1080
+ if (is_fscache_enabled (fname )) {
1081
+ if (lstat (fname , & st ) < 0 ) {
1082
+ fd = -1 ;
1083
+ } else {
1084
+ fd = open (fname , O_RDONLY );
1085
+ if (fd < 0 )
1086
+ warn_on_fopen_errors (fname );
1087
+ else if (S_ISLNK (st .st_mode ) && fstat (fd , & st ) < 0 ) {
1088
+ warn_on_fopen_errors (fname );
1089
+ close (fd );
1090
+ fd = -1 ;
1091
+ }
1092
+ }
1093
+ } else {
1094
+ fd = open (fname , O_RDONLY );
1095
+ if (fd < 0 || fstat (fd , & st ) < 0 ) {
1096
+ if (fd < 0 )
1097
+ warn_on_fopen_errors (fname );
1098
+ else {
1099
+ close (fd );
1100
+ fd = -1 ;
1101
+ }
1102
+ }
1103
+ }
1104
+
1105
+ if (fd < 0 ) {
1063
1106
if (!istate )
1064
1107
return -1 ;
1065
1108
r = read_skip_worktree_file_from_index (istate , fname ,
0 commit comments