Skip to content

Commit

Permalink
Merge pull request #3447 from jeffhostetler/try-v4-fsmonitor
Browse files Browse the repository at this point in the history
Replace pre-V4 of FSMonitor with V4 candidate
  • Loading branch information
dscho authored and Git for Windows Build Agent committed Oct 13, 2021
2 parents 53e5d27 + 0cbc4bd commit c3f08d1
Show file tree
Hide file tree
Showing 58 changed files with 6,244 additions and 311 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
/git-format-patch
/git-fsck
/git-fsck-objects
/git-fsmonitor--daemon
/git-gc
/git-get-tar-commit-id
/git-grep
Expand Down
56 changes: 42 additions & 14 deletions Documentation/config/core.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,50 @@ core.protectNTFS::
Defaults to `true` on Windows, and `false` elsewhere.

core.fsmonitor::
If set, the value of this variable is used as a command which
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].
If set, this variable contains the pathname of the "fsmonitor"
hook command.
+
This hook command is used to identify all files that may have changed
since the requested date/time. This information is used to speed up
git by avoiding unnecessary scanning of files that have not changed.
+
See the "fsmonitor-watchman" section of linkgit:githooks[5].
+
Note: The value of this config setting is ignored if the (experimental)
built-in file system monitor is enabled (see `core.useBuiltinFSMonitor`).

core.fsmonitorHookVersion::
Sets the version of hook that is to be used when calling fsmonitor.
There are currently versions 1 and 2. When this is not set,
version 2 will be tried first and if it fails then version 1
will be tried. Version 1 uses a timestamp as input to determine
which files have changes since that time but some monitors
like watchman have race conditions when used with a timestamp.
Version 2 uses an opaque string so that the monitor can return
something that can be used to determine what files have changed
without race conditions.
Sets the protocol version to be used when invoking the
"fsmonitor" hook.
+
There are currently versions 1 and 2. When this is not set,
version 2 will be tried first and if it fails then version 1
will be tried. Version 1 uses a timestamp as input to determine
which files have changes since that time but some monitors
like Watchman have race conditions when used with a timestamp.
Version 2 uses an opaque string so that the monitor can return
something that can be used to determine what files have changed
without race conditions.
+
Note: The value of this config setting is ignored if the
built-in file system monitor is enabled (see `core.useBuiltinFSMonitor`).

core.useBuiltinFSMonitor::
(EXPERIMENTAL) If set to true, enable the built-in file system monitor
daemon for this working directory (linkgit:git-fsmonitor--daemon[1]).
+
Like hook-based file system monitors, the built-in file system monitor
can speed up Git commands that need to refresh the Git index
(e.g. `git status`) in a working directory with many files. The
built-in monitor eliminates the need to install and maintain an
external third-party tool.
+
The built-in file system monitor is currently available only on a
limited set of supported platforms. Currently, this includes Windows
and MacOS.
+
Note: if this config setting is set to `true`, the values of
`core.fsmonitor` and `core.fsmonitorHookVersion` are ignored.

core.trustctime::
If false, the ctime differences between the index and the
Expand Down
78 changes: 78 additions & 0 deletions Documentation/git-fsmonitor--daemon.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
git-fsmonitor--daemon(1)
========================

NAME
----
git-fsmonitor--daemon - (EXPERIMENTAL) A Built-in File System Monitor

SYNOPSIS
--------
[verse]
'git fsmonitor--daemon' start
'git fsmonitor--daemon' run
'git fsmonitor--daemon' stop
'git fsmonitor--daemon' status

DESCRIPTION
-----------

NOTE! This command is still only an experiment, subject to change dramatically
(or even to be abandoned).

A daemon to watch the working directory for file and directory
changes using platform-specific file system notification facilities.

This daemon communicates directly with commands like `git status`
using the link:technical/api-simple-ipc.html[simple IPC] interface
instead of the slower linkgit:githooks[5] interface.

This daemon is built into Git so that no third-party tools are
required.

OPTIONS
-------

start::
Starts a daemon in the background.

run::
Runs a daemon in the foreground.

stop::
Stops the daemon running in the current working
directory, if present.

status::
Exits with zero status if a daemon is watching the
current working directory.

REMARKS
-------

This daemon is a long running process used to watch a single working
directory and maintain a list of the recently changed files and
directories. Performance of commands such as `git status` can be
increased if they just ask for a summary of changes to the working
directory and can avoid scanning the disk.

When `core.useBuiltinFSMonitor` is set to `true` (see
linkgit:git-config[1]) commands, such as `git status`, will ask the
daemon for changes and automatically start it (if necessary).

For more information see the "File System Monitor" section in
linkgit:git-update-index[1].

CAVEATS
-------

The fsmonitor daemon does not currently know about submodules and does
not know to filter out file system events that happen within a
submodule. If fsmonitor daemon is watching a super repo and a file is
modified within the working directory of a submodule, it will report
the change (as happening against the super repo). However, the client
will properly ignore these extra events, so performance may be affected
but it will not cause an incorrect result.

GIT
---
Part of the linkgit:git[1] suite
27 changes: 15 additions & 12 deletions Documentation/git-update-index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,9 @@ 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
It enables git to work together with a file system monitor (see
linkgit:git-fsmonitor--daemon[1]
and 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.
Expand All @@ -508,17 +510,18 @@ performance by avoiding the cost of scanning 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 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.
the `core.fsmonitor` or `core.useBuiltinFSMonitor` 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 in your `$HOME/.gitconfig` just once and have
it affect all repositories you touch.

When the `core.fsmonitor` or `core.useBuiltinFSMonitor` 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
-------------
Expand Down
3 changes: 2 additions & 1 deletion Documentation/githooks.txt
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ fsmonitor-watchman

This hook is invoked when the configuration option `core.fsmonitor` is
set to `.git/hooks/fsmonitor-watchman` or `.git/hooks/fsmonitor-watchmanv2`
depending on the version of the hook to use.
depending on the version of the hook to use, unless overridden via
`core.useBuiltinFSMonitor` (see linkgit:git-config[1]).

Version 1 takes two arguments, a version (1) and the time in elapsed
nanoseconds since midnight, January 1, 1970.
Expand Down
40 changes: 40 additions & 0 deletions Documentation/technical/api-trace2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,46 @@ stopping after the waitpid() and includes OS process creation overhead).
So this time will be slightly larger than the atexit time reported by
the child process itself.

`"child_ready"`::
This event is generated after the current process has started
a background process and released all handles to it.
+
------------
{
"event":"child_ready",
...
"child_id":2,
"pid":14708, # child PID
"ready":"ready", # child ready state
"t_rel":0.110605 # observed run-time of child process
}
------------
+
Note that the session-id of the child process is not available to
the current/spawning process, so the child's PID is reported here as
a hint for post-processing. (But it is only a hint because the child
process may be a shell script which doesn't have a session-id.)
+
This event is generated after the child is started in the background
and given a little time to boot up and start working. If the child
startups normally and while the parent is still waiting, the "ready"
field will have the value "ready".
If the child is too slow to start and the parent times out, the field
will have the value "timeout".
If the child starts but the parent is unable to probe it, the field
will have the value "error".
+
After the parent process emits this event, it will release all of its
handles to the child process and treat the child as a background
daemon. So even if the child does eventually finish booting up,
the parent will not emit an updated event.
+
Note that the `t_rel` field contains the observed run time in seconds
when the parent released the child process into the background.
The child is assumed to be a long-running daemon process and may
outlive the parent process. So the parent's child event times should
not be compared to the child's atexit times.

`"exec"`::
This event is generated before git attempts to `exec()`
another command rather than starting a child process.
Expand Down
32 changes: 32 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,17 @@ all::
# directory, and the JSON compilation database 'compile_commands.json' will be
# created at the root of the repository.
#
# If your platform supports a built-in fsmonitor backend, set
# FSMONITOR_DAEMON_BACKEND to the "<name>" of the corresponding
# `compat/fsmonitor/fsm-listen-<name>.c` and
# `compat/fsmonitor/fsm-health-<name>.c` files
# that implement the `fsm_listen__*()` and `fsm_health__*()` routines.
#
# If your platform has os-specific ways to tell if a repo is incompatible with
# fsmonitor (whether the hook or ipc daemon version), set FSMONITOR_OS_SETTINGS
# to the "<name>" of the corresponding `compat/fsmonitor/fsm-settings-<name>.c`
# that implements the `fsm_os_settings__*()` routines.
#
# Define DEVELOPER to enable more compiler warnings. Compiler version
# and family are auto detected, but could be overridden by defining
# COMPILER_FEATURES (see config.mak.dev). You can still set
Expand Down Expand Up @@ -707,6 +718,7 @@ TEST_BUILTINS_OBJS += test-dump-split-index.o
TEST_BUILTINS_OBJS += test-dump-untracked-cache.o
TEST_BUILTINS_OBJS += test-example-decorate.o
TEST_BUILTINS_OBJS += test-fast-rebase.o
TEST_BUILTINS_OBJS += test-fsmonitor-client.o
TEST_BUILTINS_OBJS += test-genrandom.o
TEST_BUILTINS_OBJS += test-genzeros.o
TEST_BUILTINS_OBJS += test-getcwd.o
Expand Down Expand Up @@ -896,6 +908,8 @@ LIB_OBJS += fetch-pack.o
LIB_OBJS += fmt-merge-msg.o
LIB_OBJS += fsck.o
LIB_OBJS += fsmonitor.o
LIB_OBJS += fsmonitor-ipc.o
LIB_OBJS += fsmonitor-settings.o
LIB_OBJS += gettext.o
LIB_OBJS += gpg-interface.o
LIB_OBJS += graph.o
Expand Down Expand Up @@ -1100,6 +1114,7 @@ BUILTIN_OBJS += builtin/fmt-merge-msg.o
BUILTIN_OBJS += builtin/for-each-ref.o
BUILTIN_OBJS += builtin/for-each-repo.o
BUILTIN_OBJS += builtin/fsck.o
BUILTIN_OBJS += builtin/fsmonitor--daemon.o
BUILTIN_OBJS += builtin/gc.o
BUILTIN_OBJS += builtin/get-tar-commit-id.o
BUILTIN_OBJS += builtin/grep.o
Expand Down Expand Up @@ -1925,6 +1940,17 @@ ifdef NEED_ACCESS_ROOT_HANDLER
COMPAT_OBJS += compat/access.o
endif

ifdef FSMONITOR_DAEMON_BACKEND
COMPAT_CFLAGS += -DHAVE_FSMONITOR_DAEMON_BACKEND
COMPAT_OBJS += compat/fsmonitor/fsm-listen-$(FSMONITOR_DAEMON_BACKEND).o
COMPAT_OBJS += compat/fsmonitor/fsm-health-$(FSMONITOR_DAEMON_BACKEND).o
endif

ifdef FSMONITOR_OS_SETTINGS
COMPAT_CFLAGS += -DHAVE_FSMONITOR_OS_SETTINGS
COMPAT_OBJS += compat/fsmonitor/fsm-settings-$(FSMONITOR_OS_SETTINGS).o
endif

ifeq ($(TCLTK_PATH),)
NO_TCLTK = NoThanks
endif
Expand Down Expand Up @@ -2812,6 +2838,12 @@ GIT-BUILD-OPTIONS: FORCE
@echo DC_SHA1=\''$(subst ','\'',$(subst ','\'',$(DC_SHA1)))'\' >>$@+
@echo SANITIZE_LEAK=\''$(subst ','\'',$(subst ','\'',$(SANITIZE_LEAK)))'\' >>$@+
@echo X=\'$(X)\' >>$@+
ifdef FSMONITOR_DAEMON_BACKEND
@echo FSMONITOR_DAEMON_BACKEND=\''$(subst ','\'',$(subst ','\'',$(FSMONITOR_DAEMON_BACKEND)))'\' >>$@+
endif
ifdef FSMONITOR_OS_SETTINGS
@echo FSMONITOR_OS_SETTINGS=\''$(subst ','\'',$(subst ','\'',$(FSMONITOR_OS_SETTINGS)))'\' >>$@+
endif
ifdef TEST_OUTPUT_DIRECTORY
@echo TEST_OUTPUT_DIRECTORY=\''$(subst ','\'',$(subst ','\'',$(TEST_OUTPUT_DIRECTORY)))'\' >>$@+
endif
Expand Down
1 change: 1 addition & 0 deletions builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
int cmd_for_each_repo(int argc, const char **argv, const char *prefix);
int cmd_format_patch(int argc, const char **argv, const char *prefix);
int cmd_fsck(int argc, const char **argv, const char *prefix);
int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix);
int cmd_gc(int argc, const char **argv, const char *prefix);
int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
int cmd_grep(int argc, const char **argv, const char *prefix);
Expand Down
Loading

0 comments on commit c3f08d1

Please sign in to comment.