Merge branch 'av/fsmonitor'

Various fixes to bp/fsmonitor topic.

* av/fsmonitor:
  fsmonitor: simplify determining the git worktree under Windows
  fsmonitor: store fsmonitor bitmap before splitting index
  fsmonitor: read from getcwd(), not the PWD environment variable
  fsmonitor: delay updating state until after split index is merged
  fsmonitor: document GIT_TRACE_FSMONITOR
  fsmonitor: don't bother pretty-printing JSON from watchman
  fsmonitor: set the PWD to the top of the working tree
This commit is contained in:
Junio C Hamano 2017-11-21 14:07:51 +09:00
commit c9fdbca92c
8 changed files with 77 additions and 48 deletions

View File

@ -595,6 +595,10 @@ into it.
Unsetting the variable, or setting it to empty, "0" or Unsetting the variable, or setting it to empty, "0" or
"false" (case insensitive) disables trace messages. "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`:: `GIT_TRACE_PACK_ACCESS`::
Enables trace messages for all accesses to any packs. For each Enables trace messages for all accesses to any packs. For each
access, the pack file name and an offset in the pack is access, the pack file name and an offset in the pack is

View File

@ -348,6 +348,7 @@ struct index_state {
unsigned char sha1[20]; unsigned char sha1[20];
struct untracked_cache *untracked; struct untracked_cache *untracked;
uint64_t fsmonitor_last_update; uint64_t fsmonitor_last_update;
struct ewah_bitmap *fsmonitor_dirty;
}; };
extern struct index_state the_index; extern struct index_state the_index;

View File

@ -26,7 +26,6 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data,
uint32_t hdr_version; uint32_t hdr_version;
uint32_t ewah_size; uint32_t ewah_size;
struct ewah_bitmap *fsmonitor_dirty; struct ewah_bitmap *fsmonitor_dirty;
int i;
int ret; int ret;
if (sz < sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t)) 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); ewah_free(fsmonitor_dirty);
return error("failed to parse ewah bitmap reading fsmonitor index extension"); return error("failed to parse ewah bitmap reading fsmonitor index extension");
} }
istate->fsmonitor_dirty = fsmonitor_dirty;
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);
trace_printf_key(&trace_fsmonitor, "read fsmonitor extension successful"); trace_printf_key(&trace_fsmonitor, "read fsmonitor extension successful");
return 0; 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) void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
{ {
uint32_t hdr_version; uint32_t hdr_version;
uint64_t tm; uint64_t tm;
struct ewah_bitmap *bitmap;
int i;
uint32_t ewah_start; uint32_t ewah_start;
uint32_t ewah_size = 0; uint32_t ewah_size = 0;
int fixup = 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 */ strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
ewah_start = sb->len; ewah_start = sb->len;
bitmap = ewah_new(); ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
for (i = 0; i < istate->cache_nr; i++) ewah_free(istate->fsmonitor_dirty);
if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) istate->fsmonitor_dirty = NULL;
ewah_set(bitmap, i);
ewah_serialize_strbuf(bitmap, sb);
ewah_free(bitmap);
/* fix up size field */ /* fix up size field */
put_be32(&ewah_size, sb->len - ewah_start); 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; argv[3] = NULL;
cp.argv = argv; cp.argv = argv;
cp.use_shell = 1; cp.use_shell = 1;
cp.dir = get_git_work_tree();
return capture_command(&cp, query_result, 1024); 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) 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 */ case -1: /* keep: do nothing */
break; break;
case 0: /* false */ case 0: /* false */

View File

@ -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); 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); extern void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate);

View File

@ -2535,6 +2535,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
int new_shared_index, ret; int new_shared_index, ret;
struct split_index *si = istate->split_index; struct split_index *si = istate->split_index;
if (istate->fsmonitor_last_update)
fill_fsmonitor_bitmap(istate);
if (!si || alternate_index_output || if (!si || alternate_index_output ||
(istate->cache_changed & ~EXTMASK)) { (istate->cache_changed & ~EXTMASK)) {
if (si) if (si)

View File

@ -301,4 +301,17 @@ do
done done
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 test_done

View File

@ -29,19 +29,13 @@ if ($version == 1) {
"Falling back to scanning...\n"; "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; my $git_work_tree;
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
if ($system =~ m/^MSYS_NT/ || $system =~ m/^MINGW/) { $git_work_tree = Win32::GetCwd();
$git_work_tree = `cygpath -aw "\$PWD"`; $git_work_tree =~ tr/\\/\//;
$git_work_tree =~ s/[\r\n]+//g;
$git_work_tree =~ s,\\,/,g;
} else { } else {
$git_work_tree = $ENV{'PWD'}; require Cwd;
$git_work_tree = Cwd::cwd();
} }
my $retry = 1; my $retry = 1;

View File

@ -28,19 +28,13 @@ if ($version == 1) {
"Falling back to scanning...\n"; "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; my $git_work_tree;
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
if ($system =~ m/^MSYS_NT/ || $system =~ m/^MINGW/) { $git_work_tree = Win32::GetCwd();
$git_work_tree = `cygpath -aw "\$PWD"`; $git_work_tree =~ tr/\\/\//;
$git_work_tree =~ s/[\r\n]+//g;
$git_work_tree =~ s,\\,/,g;
} else { } else {
$git_work_tree = $ENV{'PWD'}; require Cwd;
$git_work_tree = Cwd::cwd();
} }
my $retry = 1; my $retry = 1;
@ -49,7 +43,7 @@ launch_watchman();
sub 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" . or die "open2() failed: $!\n" .
"Falling back to scanning...\n"; "Falling back to scanning...\n";