Subject: Fast git status via a file system watcher
Thanks to everyone who provided feedback. There are lots of minor style
changes, documentation updates and a fixed leak.
The only functional change is the addition of support to set/clear the
fsmonitor valid bit via 'git update-index --[no-]fsmonitor-valid' with
the associated documentation and tests.
Interdiff between V6 and V7:
diff --git a/Documentation/config.txt b/Documentation/config.txt
index c196007a27..db52645cb4 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -418,6 +418,7 @@ core.fsmonitor::
will identify all files that may have changed since the
requested date/time. This information is used to speed up git by
avoiding unnecessary processing of files that have not changed.
+ See the "fsmonitor-watchman" section of linkgit:githooks[5].
core.trustctime::
If false, the ctime differences between the index and the
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index d153c17e06..3ac3e3a77d 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -9,7 +9,7 @@ git-ls-files - Show information about files in the index and
the working tree
SYNOPSIS
--------
[verse]
-'git ls-files' [-z] [-t] [-v]
+'git ls-files' [-z] [-t] [-v] [-f]
(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])*
(-[c|d|o|i|s|u|k|m])*
[--eol]
@@ -133,6 +133,11 @@ a space) at the start of each line:
that are marked as 'assume unchanged' (see
linkgit:git-update-index[1]).
+-f::
+ Similar to `-t`, but use lowercase letters for files
+ that are marked as 'fsmonitor valid' (see
+ linkgit:git-update-index[1]).
+
--full-name::
When run from a subdirectory, the command usually
outputs paths relative to the current directory. This
diff --git a/Documentation/git-update-index.txt
b/Documentation/git-update-index.txt
index e19eba62cd..95231dbfcb 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -16,9 +16,11 @@ SYNOPSIS
[--chmod=(+|-)x]
[--[no-]assume-unchanged]
[--[no-]skip-worktree]
+ [--[no-]fsmonitor-valid]
[--ignore-submodules]
[--[no-]split-index]
[--[no-|test-|force-]untracked-cache]
+ [--[no-]fsmonitor]
[--really-refresh] [--unresolve] [--again | -g]
[--info-only] [--index-info]
[-z] [--stdin] [--index-version <n>]
@@ -111,6 +113,12 @@ you will need to handle the situation manually.
set and unset the "skip-worktree" bit for the paths. See
section "Skip-worktree bit" below for more information.
+--[no-]fsmonitor-valid::
+ When one of these flags is specified, the object name recorded
+ for the paths are not updated. Instead, these options
+ set and unset the "fsmonitor valid" bit for the paths. See
+ section "File System Monitor" below for more information.
+
-g::
--again::
Runs 'git update-index' itself on the paths whose index
@@ -201,6 +209,15 @@ will remove the intended effect of the option.
`--untracked-cache` used to imply `--test-untracked-cache` but
this option would enable the extension unconditionally.
+--fsmonitor::
+--no-fsmonitor::
+ Enable or disable files system monitor feature. These options
+ take effect whatever the value of the `core.fsmonitor`
+ configuration variable (see linkgit:git-config[1]). But a warning
+ is emitted when the change goes against the configured value, as
+ the configured value will take effect next time the index is
+ read and this will remove the intended effect of the option.
+
\--::
Do not interpret any more arguments as options.
@@ -447,6 +464,34 @@ command reads the index; while when
`--[no-|force-]untracked-cache`
are used, the untracked cache is immediately added to or removed from
the index.
+File System Monitor
+-------------------
+
+This feature is intended to speed up git operations for repos that have
+large working directories.
+
+It enables git to work together with a file system monitor (see the
+"fsmonitor-watchman" section of linkgit:githooks[5]) that can
+inform it as to what files have been modified. This enables git to avoid
+having to lstat() every file to find modified files.
+
+When used in conjunction with the untracked cache, it can further improve
+performance by avoiding the cost of scaning the entire working directory
+looking for new files.
+
+If you want to enable (or disable) this feature, it is easier to use
+the `core.fsmonitor` configuration variable (see
+linkgit:git-config[1]) than using the `--fsmonitor` option to
+`git update-index` in each repository, especially if you want to do so
+across all repositories you use, because you can set the configuration
+variable to `true` (or `false`) in your `$HOME/.gitconfig` just once
+and have it affect all repositories you touch.
+
+When the `core.fsmonitor` configuration variable is changed, the
+file system monitor is added to or removed from the index the next time
+a command reads the index. When `--[no-]fsmonitor` are used, the file
+system monitor is immediately added to or removed from the index.
+
Configuration
-------------
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index da82d64b0b..ae60559cd9 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -455,10 +455,8 @@ the name of the file that holds the e-mail to be sent.
Exiting with a
non-zero status causes 'git send-email' to abort before sending any
e-mails.
-
-[[fsmonitor-watchman]]
fsmonitor-watchman
-~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~
This hook is invoked when the configuration option core.fsmonitor is
set to .git/hooks/fsmonitor-watchman. It takes two arguments, a version
@@ -471,10 +469,17 @@ should be inclusive so that it does not miss any
potential changes.
The paths should be relative to the root of the working directory
and be separated by a single NUL.
+It is OK to include files which have not actually changed. All changes
+including newly-created and deleted files should be included. When
+files are renamed, both the old and the new name should be included.
+
Git will limit what files it checks for changes as well as which
directories are checked for untracked files based on the path names
given.
+An optimized way to tell git "all files have changed" is to return
+the filename '/'.
+
The exit status determines whether git will use the data from the
hook to limit its search. On error, it will fall back to verifying
all files and folders.
diff --git a/builtin/update-index.c b/builtin/update-index.c
index b03afc1f3a..41618db098 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -33,6 +33,7 @@ static int force_remove;
static int verbose;
static int mark_valid_only;
static int mark_skip_worktree_only;
+static int mark_fsmonitor_only;
#define MARK_FLAG 1
#define UNMARK_FLAG 2
static struct strbuf mtime_dir = STRBUF_INIT;
@@ -229,12 +230,12 @@ static int mark_ce_flags(const char *path, int flag, int
mark)
int namelen = strlen(path);
int pos = cache_name_pos(path, namelen);
if (0 <= pos) {
+ mark_fsmonitor_invalid(&the_index, active_cache[pos]);
if (mark)
active_cache[pos]->ce_flags |= flag;
else
active_cache[pos]->ce_flags &= ~flag;
active_cache[pos]->ce_flags |= CE_UPDATE_IN_BASE;
- mark_fsmonitor_invalid(&the_index, active_cache[pos]);
cache_tree_invalidate_path(&the_index, path);
active_cache_changed |= CE_ENTRY_CHANGED;
return 0;
@@ -460,6 +461,11 @@ static void update_one(const char *path)
die("Unable to mark file %s", path);
return;
}
+ if (mark_fsmonitor_only) {
+ if (mark_ce_flags(path, CE_FSMONITOR_VALID, mark_fsmonitor_only
== MARK_FLAG))
+ die("Unable to mark file %s", path);
+ return;
+ }
if (force_remove) {
if (remove_file_from_cache(path))
@@ -1014,6 +1020,12 @@ int cmd_update_index(int argc, const char **argv, const
char *prefix)
N_("write out the index even if is not flagged as
changed"), 1),
OPT_BOOL(0, "fsmonitor", &fsmonitor,
N_("enable or disable file system monitor")),
+ {OPTION_SET_INT, 0, "fsmonitor-valid", &mark_fsmonitor_only,
NULL,
+ N_("mark files as fsmonitor valid"),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
+ {OPTION_SET_INT, 0, "no-fsmonitor-valid", &mark_fsmonitor_only,
NULL,
+ N_("clear fsmonitor valid bit"),
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
OPT_END()
};
diff --git a/fsmonitor.c b/fsmonitor.c
index 144294b8df..b8b2d88fe1 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c
@@ -57,12 +57,12 @@ int read_fsmonitor_extension(struct index_state *istate,
const void *data,
/* Mark all previously saved entries as dirty */
ewah_each_bit(fsmonitor_dirty, fsmonitor_ewah_callback, istate);
- ewah_free(fsmonitor_dirty);
/* 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");
return 0;
@@ -177,7 +177,7 @@ void refresh_fsmonitor(struct index_state *istate)
}
/* a fsmonitor process can return '*' to indicate all entries are
invalid */
- if (query_success && query_result.buf[0] != '*') {
+ if (query_success && query_result.buf[0] != '/') {
/* Mark all entries returned by the monitor as dirty */
buf = query_result.buf;
bol = 0;
diff --git a/fsmonitor.h b/fsmonitor.h
index dadbe90283..c2240b811a 100644
--- a/fsmonitor.h
+++ b/fsmonitor.h
@@ -46,7 +46,7 @@ static inline void mark_fsmonitor_valid(struct cache_entry
*ce)
}
/*
- * Clear the given cache entries CE_FSMONITOR_VALID bit and invalidate any
+ * Clear the given cache entry's CE_FSMONITOR_VALID bit and invalidate any
* corresponding untracked cache directory structures.
*/
static inline void mark_fsmonitor_invalid(struct index_state *istate, struct
cache_entry *ce)
diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c
index 717079865c..4e5ca8f397 100644
--- a/t/helper/test-drop-caches.c
+++ b/t/helper/test-drop-caches.c
@@ -2,7 +2,7 @@
#if defined(GIT_WINDOWS_NATIVE)
-int cmd_sync(void)
+static int cmd_sync(void)
{
char Buffer[MAX_PATH];
DWORD dwRet;
@@ -49,7 +49,7 @@ typedef enum _SYSTEM_MEMORY_LIST_COMMAND {
MemoryCommandMax
} SYSTEM_MEMORY_LIST_COMMAND;
-BOOL GetPrivilege(HANDLE TokenHandle, LPCSTR lpName, int flags)
+static BOOL GetPrivilege(HANDLE TokenHandle, LPCSTR lpName, int flags)
{
BOOL bResult;
DWORD dwBufferLength;
@@ -77,10 +77,11 @@ BOOL GetPrivilege(HANDLE TokenHandle, LPCSTR lpName, int
flags)
return bResult;
}
-int cmd_dropcaches(void)
+static int cmd_dropcaches(void)
{
HANDLE hProcess = GetCurrentProcess();
HANDLE hToken;
+ HMODULE ntdll;
int status;
if (!OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
&hToken))
@@ -91,7 +92,7 @@ int cmd_dropcaches(void)
CloseHandle(hToken);
- HMODULE ntdll = LoadLibrary("ntdll.dll");
+ ntdll = LoadLibrary("ntdll.dll");
if (!ntdll)
return error("Can't load ntdll.dll, wrong Windows version?");
@@ -118,36 +119,36 @@ int cmd_dropcaches(void)
#elif defined(__linux__)
-int cmd_sync(void)
+static int cmd_sync(void)
{
return system("sync");
}
-int cmd_dropcaches(void)
+static int cmd_dropcaches(void)
{
return system("echo 3 | sudo tee /proc/sys/vm/drop_caches");
}
#elif defined(__APPLE__)
-int cmd_sync(void)
+static int cmd_sync(void)
{
return system("sync");
}
-int cmd_dropcaches(void)
+static int cmd_dropcaches(void)
{
return system("sudo purge");
}
#else
-int cmd_sync(void)
+static int cmd_sync(void)
{
return 0;
}
-int cmd_dropcaches(void)
+static int cmd_dropcaches(void)
{
return error("drop caches not implemented on this platform");
}
diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c
index 482d749bb9..ad452707e8 100644
--- a/t/helper/test-dump-fsmonitor.c
+++ b/t/helper/test-dump-fsmonitor.c
@@ -12,7 +12,7 @@ int cmd_main(int ac, const char **av)
printf("no fsmonitor\n");
return 0;
}
- printf("fsmonitor last update %"PRIuMAX"\n",
istate->fsmonitor_last_update);
+ printf("fsmonitor last update %"PRIuMAX"\n",
(uintmax_t)istate->fsmonitor_last_update);
for (i = 0; i < istate->cache_nr; i++)
printf((istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) ? "+"
: "-");
diff --git a/t/perf/p7519-fsmonitor.sh b/t/perf/p7519-fsmonitor.sh
index 1c5978d5c8..16d1bf72e5 100755
--- a/t/perf/p7519-fsmonitor.sh
+++ b/t/perf/p7519-fsmonitor.sh
@@ -95,7 +95,7 @@ test_expect_success "setup for fsmonitor" '
INTEGRATION_SCRIPT="$GIT_PERF_7519_FSMONITOR"
else
#
- # Choose integration script based on existance of Watchman.
+ # Choose integration script based on existence of Watchman.
# If Watchman exists, watch the work tree and attempt a query.
# If everything succeeds, use Watchman integration script,
# else fall back to an empty integration script.
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index 6aa1e4e924..c6df85af5e 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -32,14 +32,16 @@ dirty_repo () {
echo 6 >dir2/new
}
-write_integration_script() {
+write_integration_script () {
write_script .git/hooks/fsmonitor-test<<-\EOF
- if [ "$#" -ne 2 ]; then
+ if test "$#" -ne 2
+ then
echo "$0: exactly 2 arguments expected"
exit 2
fi
- if [ "$1" != 1 ]; then
- echo -e "Unsupported core.fsmonitor hook version.\n" >&2
+ if test "$1" != 1
+ then
+ echo "Unsupported core.fsmonitor hook version." >&2
exit 1
fi
printf "untracked\0"
@@ -100,6 +102,43 @@ test_expect_success 'update-index --no-fsmonitor" removes
the fsmonitor extensio
grep "^no fsmonitor" actual
'
+cat >expect <<EOF &&
+h dir1/modified
+H dir1/tracked
+h dir2/modified
+H dir2/tracked
+h modified
+H tracked
+EOF
+
+# test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit
+test_expect_success 'update-index --fsmonitor-valid" sets the fsmonitor valid
bit' '
+ git update-index --fsmonitor &&
+ git update-index --fsmonitor-valid dir1/modified &&
+ git update-index --fsmonitor-valid dir2/modified &&
+ git update-index --fsmonitor-valid modified &&
+ git ls-files -f >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<EOF &&
+H dir1/modified
+H dir1/tracked
+H dir2/modified
+H dir2/tracked
+H modified
+H tracked
+EOF
+
+# test that "update-index --no-fsmonitor-valid" clears the fsmonitor valid bit
+test_expect_success 'update-index --no-fsmonitor-valid" clears the fsmonitor
valid bit' '
+ git update-index --no-fsmonitor-valid dir1/modified &&
+ git update-index --no-fsmonitor-valid dir2/modified &&
+ git update-index --no-fsmonitor-valid modified &&
+ git ls-files -f >actual &&
+ test_cmp expect actual
+'
+
cat >expect <<EOF &&
H dir1/modified
H dir1/tracked
@@ -204,7 +243,7 @@ for preload_val in $preload_values
do
test_expect_success "setup preloadIndex to $preload_val" '
git config core.preloadIndex $preload_val &&
- if [ $preload_val -eq true ]
+ if test $preload_val = true
then
GIT_FORCE_PRELOAD_TEST=$preload_val; export
GIT_FORCE_PRELOAD_TEST
else
@@ -249,8 +288,14 @@ do
git status >actual &&
test_path_is_file marker &&
test_i18ngrep ! "Changes not staged for commit:" actual
&&
- if [ $uc_val -eq true ]; then test_i18ngrep !
"Untracked files:" actual; fi &&
- if [ $uc_val -eq false ]; then test_i18ngrep "Untracked
files:" actual; fi &&
+ if test $uc_val = true
+ then
+ test_i18ngrep ! "Untracked files:" actual
+ fi &&
+ if test $uc_val = false
+ then
+ test_i18ngrep "Untracked files:" actual
+ fi &&
rm -f marker
'
done
diff --git a/t/t7519/fsmonitor-all b/t/t7519/fsmonitor-all
index a3870e431e..691bc94dc2 100755
--- a/t/t7519/fsmonitor-all
+++ b/t/t7519/fsmonitor-all
@@ -9,15 +9,16 @@
#
#echo "$0 $*" >&2
-if [ "$#" -ne 2 ] ; then
- echo -e "$0: exactly 2 arguments expected\n" >&2
+if test "$#" -ne 2
+then
+ echo "$0: exactly 2 arguments expected" >&2
exit 2
fi
-if [ "$1" != 1 ]
+if test "$1" != 1
then
- echo -e "Unsupported core.fsmonitor hook version.\n" >&2
+ echo "Unsupported core.fsmonitor hook version." >&2
exit 1
fi
-echo "*"
\ No newline at end of file
+echo "/"
diff --git a/t/t7519/fsmonitor-none b/t/t7519/fsmonitor-none
index c500bb0f26..ed9cf5a6a9 100755
--- a/t/t7519/fsmonitor-none
+++ b/t/t7519/fsmonitor-none
@@ -9,13 +9,14 @@
#
#echo "$0 $*" >&2
-if [ "$#" -ne 2 ] ; then
- echo -e "$0: exactly 2 arguments expected\n" >&2
+if test "$#" -ne 2
+then
+ echo "$0: exactly 2 arguments expected" >&2
exit 2
fi
-if [ "$1" != 1 ]
+if test "$1" != 1
then
- echo -e "Unsupported core.fsmonitor hook version.\n" >&2
+ echo "Unsupported core.fsmonitor hook version." >&2
exit 1
fi
diff --git a/t/t7519/fsmonitor-watchman b/t/t7519/fsmonitor-watchman
index aaee5d1fe3..7ceb32dc18 100755
--- a/t/t7519/fsmonitor-watchman
+++ b/t/t7519/fsmonitor-watchman
@@ -17,7 +17,7 @@ use IPC::Open2;
# 'git config core.fsmonitor .git/hooks/query-watchman'
#
my ($version, $time) = @ARGV;
-print STDERR "$0 $version $time\n";
+#print STDERR "$0 $version $time\n";
# Check the hook interface version
@@ -29,7 +29,20 @@ if ($version == 1) {
"Falling back to scanning...\n";
}
-my $git_work_tree = $ENV{'PWD'};
+# 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/) {
+ $git_work_tree = `cygpath -aw "\$PWD"`;
+ $git_work_tree =~ s/[\r\n]+//g;
+ $git_work_tree =~ s,\\,/,g;
+} else {
+ $git_work_tree = $ENV{'PWD'};
+}
my $retry = 1;
@@ -57,20 +70,19 @@ sub launch_watchman {
# creation clock (cclock) newer than $time_t value and will also not
# currently exist.
+ my $query = <<" END";
+ ["query", "$git_work_tree", {
+ "since": $time,
+ "fields": ["name"],
+ "expression": ["not", ["allof", ["since", $time,
"cclock"], ["not", "exists"]]]
+ }]
+ END
+
open (my $fh, ">", ".git/watchman-query.json");
- print $fh "[\"query\", \"$git_work_tree\", { \
- \"since\": $time, \
- \"fields\": [\"name\"], \
- \"expression\": [\"not\", [\"allof\", [\"since\", $time, \"cclock\"],
[\"not\", \"exists\"]]] \
- }]";
+ print $fh $query;
close $fh;
- print CHLD_IN "[\"query\", \"$git_work_tree\", { \
- \"since\": $time, \
- \"fields\": [\"name\"], \
- \"expression\": [\"not\", [\"allof\", [\"since\", $time, \"cclock\"],
[\"not\", \"exists\"]]] \
- }]";
-
+ print CHLD_IN $query;
my $response = <CHLD_OUT>;
open ($fh, ">", ".git/watchman-response.json");
@@ -100,17 +112,17 @@ sub launch_watchman {
qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
- # return fast "everything is dirty" flag"
- print "*\0";
- open ($fh, ">", ".git/watchman-output.out");
- print "*\0";
- close $fh;
# 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.
- print "*\0";
+
+ open ($fh, ">", ".git/watchman-output.out");
+ print "/\0";
+ close $fh;
+
+ print "/\0";
eval { launch_watchman() };
exit 0;
}
@@ -118,11 +130,11 @@ sub launch_watchman {
die "Watchman: $o->{error}.\n" .
"Falling back to scanning...\n" if $o->{error};
- binmode STDOUT, ":utf8";
- local $, = "\0";
- print @{$o->{files}};
-
open ($fh, ">", ".git/watchman-output.out");
print $fh @{$o->{files}};
close $fh;
-}
\ No newline at end of file
+
+ binmode STDOUT, ":utf8";
+ local $, = "\0";
+ print @{$o->{files}};
+}
diff --git a/templates/hooks--fsmonitor-watchman.sample
b/templates/hooks--fsmonitor-watchman.sample
index 2779d7edf3..870a59d237 100755
--- a/templates/hooks--fsmonitor-watchman.sample
+++ b/templates/hooks--fsmonitor-watchman.sample
@@ -69,12 +69,15 @@ sub launch_watchman {
# creation clock (cclock) newer than $time_t value and will also not
# currently exist.
- print CHLD_IN "[\"query\", \"$git_work_tree\", { \
- \"since\": $time, \
- \"fields\": [\"name\"], \
- \"expression\": [\"not\", [\"allof\", [\"since\", $time, \"cclock\"],
[\"not\", \"exists\"]]] \
- }]";
-
+ my $query = <<" END";
+ ["query", "$git_work_tree", {
+ "since": $time,
+ "fields": ["name"],
+ "expression": ["not", ["allof", ["since", $time,
"cclock"], ["not", "exists"]]]
+ }]
+ END
+
+ print CHLD_IN $query;
my $response = <CHLD_OUT>;
die "Watchman: command returned no output.\n" .
@@ -105,7 +108,7 @@ sub launch_watchman {
# 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.
- print "*\0";
+ print "/\0";
eval { launch_watchman() };
exit 0;
}
Ben Peart (12):
bswap: add 64 bit endianness helper get_be64
preload-index: add override to enable testing preload-index
update-index: add a new --force-write-index option
fsmonitor: teach git to optionally utilize a file system monitor to
speed up detecting new or changed files.
fsmonitor: add documentation for the fsmonitor extension.
ls-files: Add support in ls-files to display the fsmonitor valid bit
update-index: add fsmonitor support to update-index
fsmonitor: add a test tool to dump the index extension
split-index: disable the fsmonitor extension when running the split
index test
fsmonitor: add test cases for fsmonitor extension
fsmonitor: add a sample integration script for Watchman
fsmonitor: add a performance test
Documentation/config.txt | 7 +
Documentation/git-ls-files.txt | 7 +-
Documentation/git-update-index.txt | 45 +++++
Documentation/githooks.txt | 28 +++
Documentation/technical/index-format.txt | 19 ++
Makefile | 3 +
apply.c | 2 +-
builtin/ls-files.c | 8 +-
builtin/update-index.c | 38 +++-
cache.h | 10 +-
compat/bswap.h | 22 +++
config.c | 14 ++
config.h | 1 +
diff-lib.c | 2 +
dir.c | 27 ++-
dir.h | 2 +
entry.c | 4 +-
environment.c | 1 +
fsmonitor.c | 253 ++++++++++++++++++++++++
fsmonitor.h | 61 ++++++
preload-index.c | 8 +-
read-cache.c | 49 ++++-
submodule.c | 2 +-
t/helper/.gitignore | 1 +
t/helper/test-drop-caches.c | 162 +++++++++++++++
t/helper/test-dump-fsmonitor.c | 21 ++
t/perf/p7519-fsmonitor.sh | 184 +++++++++++++++++
t/t1700-split-index.sh | 1 +
t/t7519-status-fsmonitor.sh | 304 +++++++++++++++++++++++++++++
t/t7519/fsmonitor-all | 24 +++
t/t7519/fsmonitor-none | 22 +++
t/t7519/fsmonitor-watchman | 140 +++++++++++++
templates/hooks--fsmonitor-watchman.sample | 122 ++++++++++++
unpack-trees.c | 8 +-
34 files changed, 1572 insertions(+), 30 deletions(-)
create mode 100644 fsmonitor.c
create mode 100644 fsmonitor.h
create mode 100644 t/helper/test-drop-caches.c
create mode 100644 t/helper/test-dump-fsmonitor.c
create mode 100755 t/perf/p7519-fsmonitor.sh
create mode 100755 t/t7519-status-fsmonitor.sh
create mode 100755 t/t7519/fsmonitor-all
create mode 100755 t/t7519/fsmonitor-none
create mode 100755 t/t7519/fsmonitor-watchman
create mode 100755 templates/hooks--fsmonitor-watchman.sample
--
2.14.1.windows.1