On Thu, May 18, 2017 at 10:13 PM, Ben Peart <peartben@xxxxxxxxx> wrote: > This hook script integrates the new fsmonitor capabilities of git with > the cross platform Watchman file watching service. To use the script: > > Download and install Watchman from https://facebook.github.io/watchman/ > and instruct Watchman to watch your working directory for changes > ('watchman watch-project /usr/src/git'). > > Rename the sample integration hook from query-fsmonitor.sample to > query-fsmonitor. > > Configure git to use the extension ('git config core.fsmonitor true') > and optionally turn on the untracked cache for optimal performance > ('git config core.untrackedcache true'). > > Signed-off-by: Ben Peart <benpeart@xxxxxxxxxxxxx> > Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> > --- > templates/hooks--query-fsmonitor.sample | 27 +++++++++++++++++++++++++++ > 1 file changed, 27 insertions(+) > create mode 100644 templates/hooks--query-fsmonitor.sample > > diff --git a/templates/hooks--query-fsmonitor.sample b/templates/hooks--query-fsmonitor.sample > new file mode 100644 > index 0000000000..4bd22f21d8 > --- /dev/null > +++ b/templates/hooks--query-fsmonitor.sample > @@ -0,0 +1,27 @@ > +#!/bin/sh > +# > +# An example hook script to integrate Watchman > +# (https://facebook.github.io/watchman/) with git to provide fast > +# git status. > +# > +# The hook is passed a time_t 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-fsmonitor" > + > +# Convert unix style paths to escaped Windows style paths > +case "$(uname -s)" in > +MINGW*|MSYS_NT*) > + GIT_WORK_TREE="$(cygpath -aw "$PWD" | sed 's,\\,\\\\,g')" > + ;; > +*) > + GIT_WORK_TREE="$PWD" > + ;; > +esac > + > +# Query Watchman for all the changes since the requested time > +echo "[\"query\", \"$GIT_WORK_TREE\", {\"since\": $1, \"fields\":[\"name\"]}]" | \ > +watchman -j | \ > +perl -e 'use JSON::PP; my $o = JSON::PP->new->utf8->decode(join("", <>)); die "Watchman: $o->{'error'}.\nFalling back to scanning...\n" if defined($o->{"error"}); print(join("\0", @{$o->{"files"}}));' I couldn't get watchman to work for me (built from source, keep getting [1]), but I hacked up something you can hopefully test & squash on top of this: # Query Watchman for all the changes since the requested time -echo "[\"query\", \"$GIT_WORK_TREE\", {\"since\": $time_t, \"fields\":[\"name\"]}]" | \ -watchman -j | \ -perl -e 'use JSON::PP; my $o = JSON::PP->new->utf8->decode(join("", <>)); die "Watchman: $o->{'error'}.\nFalling back to scanning...\n" if defined($o- +echo "[\"query\", \"$GIT_WORK_TREE\", {\"since\": $time_t, \"fields\":[\"name\"]}]" | + watchman -j | + perl -0666 -e ' + use strict; + use warnings; + + my $stdin = <>; + die "Watchman: The watchman command returned no output, error above?\n" if $stdin eq ""; + die "Watchman: Invalid input: $stdin\n" unless $stdin =~ /^\{/; + + 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($stdin); + die "Watchman: $o->{error}.\nFalling back to scanning...\n" + if $o->{error}; + + local $, = "\0"; + print @{$o->{files}}; + ' Rationale: * We use the much faster JSON::XS if it's installed. * We use strict/warnings * Micro optimization: Replace joining stdin with an equivalent -0666 invocation. See "perldoc perlrun". * Micro optimization: No need to join up the possibly large list of files into one big string, just set $, to \0 and stream out the array. * Error handling: My watchman is broken (so actually this isn't tested), it only spews to stderr and exits. Handle that by checking whether stdin is "". Those changes are available at https://github.com/avar/git/commits/avar/fsmonitor 1. watchman: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.11' not found (required by watchman)