aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Tarjan <github@paulisageek.com>2026-02-28 17:37:57 +0000
committerJunio C Hamano <gitster@pobox.com>2026-03-02 08:15:18 -0800
commit41366e46779865164e3e8af2bac6eb95ea6f6586 (patch)
treed4ce4994fef7c35baf0d304a762f2f3deb4ea1dc
parent67ad42147a7acc2af6074753ebd03d904476118f (diff)
downloadgit-41366e46779865164e3e8af2bac6eb95ea6f6586.tar.xz
fsmonitor-watchman: fix variable reference and remove redundant code
The is_work_tree_watched() function in fsmonitor-watchman.sample has two bugs: 1. Wrong variable in error check: After calling watchman_clock(), the result is stored in $o, but the code checks $output->{error} instead of $o->{error}. This means errors from the clock command are silently ignored. 2. Double output violates protocol: When the retry path triggers (the directory wasn't initially watched), output_result() is called with the "/" flag, then launch_watchman() is called recursively which calls output_result() again. This outputs two clock tokens to stdout, but git's fsmonitor v2 protocol expects exactly one response. Fix #1 by checking $o->{error} after watchman_clock(). Fix #2 by removing the recursive launch_watchman() call. The "/" "everything is dirty" flag already tells git to do a full scan, and git will call the hook again on the next invocation with a valid clock token. With the recursive call removed, the $retry guard is no longer needed since it only existed to prevent infinite recursion. Remove it. Apply the same fixes to the test helper scripts in t/t7519/. Signed-off-by: Paul Tarjan <github@paulisageek.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rwxr-xr-xt/t7519/fsmonitor-watchman6
-rwxr-xr-xt/t7519/fsmonitor-watchman-v210
-rwxr-xr-xtemplates/hooks/fsmonitor-watchman.sample10
3 files changed, 5 insertions, 21 deletions
diff --git a/t/t7519/fsmonitor-watchman b/t/t7519/fsmonitor-watchman
index 264b9daf83..bcc055c1e0 100755
--- a/t/t7519/fsmonitor-watchman
+++ b/t/t7519/fsmonitor-watchman
@@ -38,8 +38,6 @@ if ($^O =~ 'msys' || $^O =~ 'cygwin') {
$git_work_tree = Cwd::cwd();
}
-my $retry = 1;
-
launch_watchman();
sub launch_watchman {
@@ -92,9 +90,8 @@ sub launch_watchman {
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/) {
+ if ($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;
@@ -109,7 +106,6 @@ sub launch_watchman {
close $fh;
print "/\0";
- eval { launch_watchman() };
exit 0;
}
diff --git a/t/t7519/fsmonitor-watchman-v2 b/t/t7519/fsmonitor-watchman-v2
index 14ed0aa42d..368604c278 100755
--- a/t/t7519/fsmonitor-watchman-v2
+++ b/t/t7519/fsmonitor-watchman-v2
@@ -29,8 +29,6 @@ if ($version ne 2) {
my $git_work_tree = get_working_dir();
-my $retry = 1;
-
my $json_pkg;
eval {
require JSON::XS;
@@ -122,8 +120,7 @@ sub watchman_query {
sub is_work_tree_watched {
my ($output) = @_;
my $error = $output->{error};
- if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
- $retry--;
+ if ($error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
my $response = qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
@@ -141,15 +138,12 @@ sub is_work_tree_watched {
# Watchman query just to get it over with now so we won't pay
# the cost in git to look up each individual file.
my $o = watchman_clock();
- $error = $output->{error};
+ $error = $o->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
output_result($o->{clock}, ("/"));
- $last_update_token = $o->{clock};
-
- eval { launch_watchman() };
return 0;
}
diff --git a/templates/hooks/fsmonitor-watchman.sample b/templates/hooks/fsmonitor-watchman.sample
index 23e856f5de..429e0a51c1 100755
--- a/templates/hooks/fsmonitor-watchman.sample
+++ b/templates/hooks/fsmonitor-watchman.sample
@@ -29,8 +29,6 @@ if ($version ne 2) {
my $git_work_tree = get_working_dir();
-my $retry = 1;
-
my $json_pkg;
eval {
require JSON::XS;
@@ -123,8 +121,7 @@ sub watchman_query {
sub is_work_tree_watched {
my ($output) = @_;
my $error = $output->{error};
- if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
- $retry--;
+ if ($error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
my $response = qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
@@ -142,15 +139,12 @@ sub is_work_tree_watched {
# Watchman query just to get it over with now so we won't pay
# the cost in git to look up each individual file.
my $o = watchman_clock();
- $error = $output->{error};
+ $error = $o->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
output_result($o->{clock}, ("/"));
- $last_update_token = $o->{clock};
-
- eval { launch_watchman() };
return 0;
}