diff --git a/Documentation/git.txt b/Documentation/git.txt index 463b0eb0f5..483a1f3547 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -595,6 +595,10 @@ into it. Unsetting the variable, or setting it to empty, "0" or "false" (case insensitive) disables trace messages. +`GIT_TRACE_FSMONITOR`:: + Enables trace messages for the filesystem monitor extension. + See `GIT_TRACE` for available trace output options. + `GIT_TRACE_PACK_ACCESS`:: Enables trace messages for all accesses to any packs. For each access, the pack file name and an offset in the pack is diff --git a/cache.h b/cache.h index 7c71681236..f684c7933b 100644 --- a/cache.h +++ b/cache.h @@ -348,6 +348,7 @@ struct index_state { unsigned char sha1[20]; struct untracked_cache *untracked; uint64_t fsmonitor_last_update; + struct ewah_bitmap *fsmonitor_dirty; }; extern struct index_state the_index; diff --git a/fsmonitor.c b/fsmonitor.c index 7c1540c054..0af7c4edba 100644 --- a/fsmonitor.c +++ b/fsmonitor.c @@ -26,7 +26,6 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data, uint32_t hdr_version; uint32_t ewah_size; struct ewah_bitmap *fsmonitor_dirty; - int i; int ret; if (sz < sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t)) @@ -49,31 +48,25 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data, ewah_free(fsmonitor_dirty); return error("failed to parse ewah bitmap reading fsmonitor index extension"); } - - if (git_config_get_fsmonitor()) { - /* Mark all entries valid */ - for (i = 0; i < istate->cache_nr; i++) - istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID; - - /* Mark all previously saved entries as dirty */ - ewah_each_bit(fsmonitor_dirty, fsmonitor_ewah_callback, istate); - - /* Now mark the untracked cache for fsmonitor usage */ - if (istate->untracked) - istate->untracked->use_fsmonitor = 1; - } - ewah_free(fsmonitor_dirty); + istate->fsmonitor_dirty = fsmonitor_dirty; trace_printf_key(&trace_fsmonitor, "read fsmonitor extension successful"); return 0; } +void fill_fsmonitor_bitmap(struct index_state *istate) +{ + int i; + istate->fsmonitor_dirty = ewah_new(); + for (i = 0; i < istate->cache_nr; i++) + if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) + ewah_set(istate->fsmonitor_dirty, i); +} + void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) { uint32_t hdr_version; uint64_t tm; - struct ewah_bitmap *bitmap; - int i; uint32_t ewah_start; uint32_t ewah_size = 0; int fixup = 0; @@ -87,12 +80,9 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */ ewah_start = sb->len; - bitmap = ewah_new(); - for (i = 0; i < istate->cache_nr; i++) - if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) - ewah_set(bitmap, i); - ewah_serialize_strbuf(bitmap, sb); - ewah_free(bitmap); + ewah_serialize_strbuf(istate->fsmonitor_dirty, sb); + ewah_free(istate->fsmonitor_dirty); + istate->fsmonitor_dirty = NULL; /* fix up size field */ put_be32(&ewah_size, sb->len - ewah_start); @@ -121,6 +111,7 @@ static int query_fsmonitor(int version, uint64_t last_update, struct strbuf *que argv[3] = NULL; cp.argv = argv; cp.use_shell = 1; + cp.dir = get_git_work_tree(); return capture_command(&cp, query_result, 1024); } @@ -238,7 +229,29 @@ void remove_fsmonitor(struct index_state *istate) void tweak_fsmonitor(struct index_state *istate) { - switch (git_config_get_fsmonitor()) { + int i; + int fsmonitor_enabled = git_config_get_fsmonitor(); + + if (istate->fsmonitor_dirty) { + if (fsmonitor_enabled) { + /* Mark all entries valid */ + for (i = 0; i < istate->cache_nr; i++) { + istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID; + } + + /* Mark all previously saved entries as dirty */ + ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate); + + /* Now mark the untracked cache for fsmonitor usage */ + if (istate->untracked) + istate->untracked->use_fsmonitor = 1; + } + + ewah_free(istate->fsmonitor_dirty); + istate->fsmonitor_dirty = NULL; + } + + switch (fsmonitor_enabled) { case -1: /* keep: do nothing */ break; case 0: /* false */ diff --git a/fsmonitor.h b/fsmonitor.h index 0de644e01a..cd3cc0ccf2 100644 --- a/fsmonitor.h +++ b/fsmonitor.h @@ -10,7 +10,14 @@ extern struct trace_key trace_fsmonitor; extern int read_fsmonitor_extension(struct index_state *istate, const void *data, unsigned long sz); /* - * Write the CE_FSMONITOR_VALID state into the fsmonitor index extension. + * Fill the fsmonitor_dirty ewah bits with their state from the index, + * before it is split during writing. + */ +extern void fill_fsmonitor_bitmap(struct index_state *istate); + +/* + * Write the CE_FSMONITOR_VALID state into the fsmonitor index + * extension. Reads from the fsmonitor_dirty ewah in the index. */ extern void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate); diff --git a/read-cache.c b/read-cache.c index 87e88b2642..fbb4967c81 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2535,6 +2535,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, int new_shared_index, ret; struct split_index *si = istate->split_index; + if (istate->fsmonitor_last_update) + fill_fsmonitor_bitmap(istate); + if (!si || alternate_index_output || (istate->cache_changed & ~EXTMASK)) { if (si) diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh index c6df85af5e..eb2d13bbcf 100755 --- a/t/t7519-status-fsmonitor.sh +++ b/t/t7519-status-fsmonitor.sh @@ -301,4 +301,17 @@ do done done +# test that splitting the index dosn't interfere +test_expect_success 'splitting the index results in the same state' ' + write_integration_script && + dirty_repo && + git update-index --fsmonitor && + git ls-files -f >expect && + test-dump-fsmonitor >&2 && echo && + git update-index --fsmonitor --split-index && + test-dump-fsmonitor >&2 && echo && + git ls-files -f >actual && + test_cmp expect actual +' + test_done diff --git a/t/t7519/fsmonitor-watchman b/t/t7519/fsmonitor-watchman index a3e30bf54f..5514edcf68 100755 --- a/t/t7519/fsmonitor-watchman +++ b/t/t7519/fsmonitor-watchman @@ -29,19 +29,13 @@ if ($version == 1) { "Falling back to scanning...\n"; } -# Convert unix style paths to escaped Windows style paths when running -# in Windows command prompt - -my $system = `uname -s`; -$system =~ s/[\r\n]+//g; my $git_work_tree; - -if ($system =~ m/^MSYS_NT/ || $system =~ m/^MINGW/) { - $git_work_tree = `cygpath -aw "\$PWD"`; - $git_work_tree =~ s/[\r\n]+//g; - $git_work_tree =~ s,\\,/,g; +if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $git_work_tree = Win32::GetCwd(); + $git_work_tree =~ tr/\\/\//; } else { - $git_work_tree = $ENV{'PWD'}; + require Cwd; + $git_work_tree = Cwd::cwd(); } my $retry = 1; diff --git a/templates/hooks--fsmonitor-watchman.sample b/templates/hooks--fsmonitor-watchman.sample index 9eba8a7409..e673bb3980 100755 --- a/templates/hooks--fsmonitor-watchman.sample +++ b/templates/hooks--fsmonitor-watchman.sample @@ -28,19 +28,13 @@ if ($version == 1) { "Falling back to scanning...\n"; } -# Convert unix style paths to escaped Windows style paths when running -# in Windows command prompt - -my $system = `uname -s`; -$system =~ s/[\r\n]+//g; my $git_work_tree; - -if ($system =~ m/^MSYS_NT/ || $system =~ m/^MINGW/) { - $git_work_tree = `cygpath -aw "\$PWD"`; - $git_work_tree =~ s/[\r\n]+//g; - $git_work_tree =~ s,\\,/,g; +if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $git_work_tree = Win32::GetCwd(); + $git_work_tree =~ tr/\\/\//; } else { - $git_work_tree = $ENV{'PWD'}; + require Cwd; + $git_work_tree = Cwd::cwd(); } my $retry = 1; @@ -49,7 +43,7 @@ launch_watchman(); sub launch_watchman { - my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j') + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') or die "open2() failed: $!\n" . "Falling back to scanning...\n";