-
Notifications
You must be signed in to change notification settings - Fork 98
fsmonitor updates for improved performance #212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,6 +106,8 @@ EOF | |
|
||
# test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit | ||
test_expect_success 'update-index --fsmonitor-valid" sets the fsmonitor valid bit' ' | ||
write_script .git/hooks/fsmonitor-test<<-\EOF && | ||
EOF | ||
kewillford marked this conversation as resolved.
Show resolved
Hide resolved
|
||
git update-index --fsmonitor && | ||
git update-index --fsmonitor-valid dir1/modified && | ||
git update-index --fsmonitor-valid dir2/modified && | ||
|
@@ -164,6 +166,8 @@ EOF | |
|
||
# test that newly added files are marked valid | ||
test_expect_success 'newly added files are marked valid' ' | ||
write_script .git/hooks/fsmonitor-test<<-\EOF && | ||
EOF | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I do not understand this diff hunk. previously, we let the test fsmonitor tell Git to look at the new files, but now we don't? Is this a diff hunk that is not exactly necessary for the test case to pass, but merely to make the test more accurate, by disallowing fsmonitor to trigger There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing this out. The issue is that with these changes the fsmonitor data is refreshed when any command reads the index. Left unchanged the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Follow up question here: what behavior is this test specifically trying to validate? The comment says:
But based on the change you made it seems like newly added files will not always be marked as valid (i.e. if they were dirty before they will still be considered dirty after the Is there there something I'm missing (e.g. was the test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe for this test the
needs to be before the I'm taking a closer look at the tests because before the content of the So in most cases we need to make sure I might also try using the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Ahh, this is the part I was missing, thanks! |
||
git add new && | ||
git add dir1/new && | ||
git add dir2/new && | ||
|
@@ -218,11 +222,12 @@ test_expect_success '*only* files returned by the integration script get flagged | |
# Ensure commands that call refresh_index() to move the index back in time | ||
# properly invalidate the fsmonitor cache | ||
test_expect_success 'refresh_index() invalidates fsmonitor cache' ' | ||
write_script .git/hooks/fsmonitor-test<<-\EOF && | ||
EOF | ||
clean_repo && | ||
dirty_repo && | ||
write_integration_script && | ||
git add . && | ||
write_script .git/hooks/fsmonitor-test<<-\EOF && | ||
EOF | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So basically the change in And then I really don't understand why we have to have the full |
||
git commit -m "to reset" && | ||
git reset HEAD~1 && | ||
git status >actual && | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#!/usr/bin/perl | ||
|
||
use strict; | ||
use warnings; | ||
use IPC::Open2; | ||
|
||
# An example hook script to integrate Watchman | ||
# (https://facebook.github.io/watchman/) with git to speed up detecting | ||
# new and modified files. | ||
# | ||
# The hook is passed a version (currently 1) and a time in nanoseconds | ||
# formatted as a string and outputs to stdout all files that have been | ||
# modified since the given time. Paths must be relative to the root of | ||
# the working tree and separated by a single NUL. | ||
# | ||
# To enable this hook, rename this file to "query-watchman" and set | ||
# 'git config core.fsmonitor .git/hooks/query-watchman' | ||
# | ||
my ($version, $time) = @ARGV; | ||
#print STDERR "$0 $version $time\n"; | ||
|
||
# Check the hook interface version | ||
|
||
if ($version == 1) { | ||
# convert nanoseconds to seconds | ||
# subtract one second to make sure watchman will return all changes | ||
$time = int ($time / 1000000000) - 1; | ||
} else { | ||
die "Unsupported query-fsmonitor hook version '$version'.\n" . | ||
"Falling back to scanning...\n"; | ||
} | ||
|
||
my $git_work_tree; | ||
if ($^O =~ 'msys' || $^O =~ 'cygwin') { | ||
$git_work_tree = Win32::GetCwd(); | ||
$git_work_tree =~ tr/\\/\//; | ||
} else { | ||
require Cwd; | ||
$git_work_tree = Cwd::cwd(); | ||
} | ||
|
||
my $retry = 1; | ||
|
||
launch_watchman(); | ||
|
||
sub launch_watchman { | ||
|
||
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j') | ||
or die "open2() failed: $!\n" . | ||
"Falling back to scanning...\n"; | ||
|
||
# In the query expression below we're asking for names of files that | ||
# changed since $time but were not transient (ie created after | ||
# $time but no longer exist). | ||
# | ||
# To accomplish this, we're using the "since" generator to use the | ||
# recency index to select candidate nodes and "fields" to limit the | ||
# output to file names only. | ||
|
||
my $query = <<" END"; | ||
["query", "$git_work_tree", { | ||
"since": $time, | ||
"fields": ["name"] | ||
}] | ||
END | ||
|
||
open (my $fh, ">", ".git/watchman-query.json"); | ||
print $fh $query; | ||
close $fh; | ||
|
||
print CHLD_IN $query; | ||
close CHLD_IN; | ||
my $response = do {local $/; <CHLD_OUT>}; | ||
|
||
open ($fh, ">", ".git/watchman-response.json"); | ||
print $fh $response; | ||
close $fh; | ||
|
||
die "Watchman: command returned no output.\n" . | ||
"Falling back to scanning...\n" if $response eq ""; | ||
die "Watchman: command returned invalid output: $response\n" . | ||
"Falling back to scanning...\n" unless $response =~ /^\{/; | ||
|
||
my $json_pkg; | ||
eval { | ||
require JSON::XS; | ||
$json_pkg = "JSON::XS"; | ||
1; | ||
} or do { | ||
require JSON::PP; | ||
$json_pkg = "JSON::PP"; | ||
}; | ||
|
||
my $o = $json_pkg->new->utf8->decode($response); | ||
|
||
if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) { | ||
print STDERR "Adding '$git_work_tree' to watchman's watch list.\n"; | ||
$retry--; | ||
qx/watchman watch "$git_work_tree"/; | ||
die "Failed to make watchman watch '$git_work_tree'.\n" . | ||
"Falling back to scanning...\n" if $? != 0; | ||
|
||
# Watchman will always return all files on the first query so | ||
# return the fast "everything is dirty" flag to git and do the | ||
# Watchman query just to get it over with now so we won't pay | ||
# the cost in git to look up each individual file. | ||
|
||
open ($fh, ">", ".git/watchman-output.out"); | ||
print "/\0"; | ||
close $fh; | ||
|
||
print "/\0"; | ||
eval { launch_watchman() }; | ||
exit 0; | ||
} | ||
|
||
die "Watchman: $o->{error}.\n" . | ||
"Falling back to scanning...\n" if $o->{error}; | ||
|
||
open ($fh, ">", ".git/watchman-output.out"); | ||
binmode $fh, ":utf8"; | ||
print $fh @{$o->{files}}; | ||
close $fh; | ||
|
||
binmode STDOUT, ":utf8"; | ||
local $, = "\0"; | ||
print @{$o->{files}}; | ||
} |
Uh oh!
There was an error while loading. Please reload this page.