Skip to content

Commit 19ee546

Browse files
jeffhostetlerGit for Windows Build Agent
authored andcommitted
dir.c: make add_excludes aware of fscache during status
Teach read_directory_recursive() and add_excludes() to be aware of optional fscache and avoid trying to open() and fstat() non-existant ".gitignore" files in every directory in the worktree. The current code in add_excludes() calls open() and then fstat() for a ".gitignore" file in each directory present in the worktree. Change that when fscache is enabled to call lstat() first and if present, call open(). This seems backwards because both lstat needs to do more work than fstat. But when fscache is enabled, fscache will already know if the .gitignore file exists and can completely avoid the IO calls. This works because of the lstat diversion to mingw_lstat when fscache is enabled. This reduced status times on a 350K file enlistment of the Windows repo on a NVMe SSD by 0.25 seconds. Signed-off-by: Jeff Hostetler <[email protected]>
1 parent 70906df commit 19ee546

File tree

4 files changed

+42
-9
lines changed

4 files changed

+42
-9
lines changed

compat/win32/fscache.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ static struct hashmap map;
1212
static CRITICAL_SECTION mutex;
1313
static struct trace_key trace_fscache = TRACE_KEY_INIT(FSCACHE);
1414

15+
int fscache_is_enabled(void)
16+
{
17+
return enabled;
18+
}
19+
1520
/*
1621
* An entry in the file system cache. Used for both entire directory listings
1722
* and file entries.

compat/win32/fscache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
int fscache_enable(int enable);
55
#define enable_fscache(x) fscache_enable(x)
66

7+
int fscache_is_enabled(void);
8+
#define is_fscache_enabled() (fscache_is_enabled())
9+
710
DIR *fscache_opendir(const char *dir);
811
int fscache_lstat(const char *file_name, struct stat *buf);
912

dir.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,16 +1115,37 @@ 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+
* Since `clang`'s `-Wunreachable-code` mode is clever, it would figure
1120+
* out that on non-Windows platforms, this `lstat()` is unreachable.
1121+
* We do want to keep the conditional block for the sake of Windows,
1122+
* though, so let's use the `NOT_CONSTANT()` trick to suppress that error.
1123+
*/
1124+
if (NOT_CONSTANT(is_fscache_enabled(fname))) {
1125+
if (lstat(fname, &st) < 0) {
1126+
fd = -1;
1127+
} else {
1128+
fd = open(fname, O_RDONLY);
1129+
if (fd < 0)
1130+
warn_on_fopen_errors(fname);
1131+
}
1132+
} else {
1133+
if (flags & PATTERN_NOFOLLOW)
1134+
fd = open_nofollow(fname, O_RDONLY);
11261135
else
1127-
close(fd);
1136+
fd = open(fname, O_RDONLY);
1137+
1138+
if (fd < 0 || fstat(fd, &st) < 0) {
1139+
if (fd < 0)
1140+
warn_on_fopen_errors(fname);
1141+
else {
1142+
close(fd);
1143+
fd = -1;
1144+
}
1145+
}
1146+
}
1147+
1148+
if (fd < 0) {
11281149
if (!istate)
11291150
return -1;
11301151
r = read_skip_worktree_file_from_index(istate, fname,

git-compat-util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,10 @@ static inline int is_missing_file_error(int errno_)
10631063
#define enable_fscache(x) /* noop */
10641064
#endif
10651065

1066+
#ifndef is_fscache_enabled
1067+
#define is_fscache_enabled() (0)
1068+
#endif
1069+
10661070
int cmd_main(int, const char **);
10671071

10681072
/*

0 commit comments

Comments
 (0)