Skip to content

Commit d0098b5

Browse files
jeffhostetlerGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
Merge branch 'try-v4-fsmonitor-part2' into try-v4-fsmonitor
2 parents e876d2c + e1d2469 commit d0098b5

18 files changed

+538
-88
lines changed

Documentation/config/core.txt

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,50 @@ core.protectNTFS::
6262
Defaults to `true` on Windows, and `false` elsewhere.
6363

6464
core.fsmonitor::
65-
If set, the value of this variable is used as a command which
66-
will identify all files that may have changed since the
67-
requested date/time. This information is used to speed up git by
68-
avoiding unnecessary processing of files that have not changed.
69-
See the "fsmonitor-watchman" section of linkgit:githooks[5].
65+
If set, this variable contains the pathname of the "fsmonitor"
66+
hook command.
67+
+
68+
This hook command is used to identify all files that may have changed
69+
since the requested date/time. This information is used to speed up
70+
git by avoiding unnecessary scanning of files that have not changed.
71+
+
72+
See the "fsmonitor-watchman" section of linkgit:githooks[5].
73+
+
74+
Note: The value of this config setting is ignored if the
75+
built-in file system monitor is enabled (see `core.useBuiltinFSMonitor`).
7076

7177
core.fsmonitorHookVersion::
72-
Sets the version of hook that is to be used when calling fsmonitor.
73-
There are currently versions 1 and 2. When this is not set,
74-
version 2 will be tried first and if it fails then version 1
75-
will be tried. Version 1 uses a timestamp as input to determine
76-
which files have changes since that time but some monitors
77-
like watchman have race conditions when used with a timestamp.
78-
Version 2 uses an opaque string so that the monitor can return
79-
something that can be used to determine what files have changed
80-
without race conditions.
78+
Sets the protocol version to be used when invoking the
79+
"fsmonitor" hook.
80+
+
81+
There are currently versions 1 and 2. When this is not set,
82+
version 2 will be tried first and if it fails then version 1
83+
will be tried. Version 1 uses a timestamp as input to determine
84+
which files have changes since that time but some monitors
85+
like Watchman have race conditions when used with a timestamp.
86+
Version 2 uses an opaque string so that the monitor can return
87+
something that can be used to determine what files have changed
88+
without race conditions.
89+
+
90+
Note: The value of this config setting is ignored if the
91+
built-in file system monitor is enabled (see `core.useBuiltinFSMonitor`).
92+
93+
core.useBuiltinFSMonitor::
94+
If set to true, enable the built-in file system monitor
95+
daemon for this working directory (linkgit:git-fsmonitor--daemon[1]).
96+
+
97+
Like hook-based file system monitors, the built-in file system monitor
98+
can speed up Git commands that need to refresh the Git index
99+
(e.g. `git status`) in a working directory with many files. The
100+
built-in monitor eliminates the need to install and maintain an
101+
external third-party tool.
102+
+
103+
The built-in file system monitor is currently available only on a
104+
limited set of supported platforms. Currently, this includes Windows
105+
and MacOS.
106+
+
107+
Note: if this config setting is set to `true`, the values of
108+
`core.fsmonitor` and `core.fsmonitorHookVersion` are ignored.
81109

82110
core.trustctime::
83111
If false, the ctime differences between the index and the

Documentation/git-update-index.txt

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,9 @@ FILE SYSTEM MONITOR
498498
This feature is intended to speed up git operations for repos that have
499499
large working directories.
500500

501-
It enables git to work together with a file system monitor (see the
501+
It enables git to work together with a file system monitor (see
502+
linkgit:git-fsmonitor--daemon[1]
503+
and the
502504
"fsmonitor-watchman" section of linkgit:githooks[5]) that can
503505
inform it as to what files have been modified. This enables git to avoid
504506
having to lstat() every file to find modified files.
@@ -508,17 +510,18 @@ performance by avoiding the cost of scanning the entire working directory
508510
looking for new files.
509511

510512
If you want to enable (or disable) this feature, it is easier to use
511-
the `core.fsmonitor` configuration variable (see
512-
linkgit:git-config[1]) than using the `--fsmonitor` option to
513-
`git update-index` in each repository, especially if you want to do so
514-
across all repositories you use, because you can set the configuration
515-
variable in your `$HOME/.gitconfig` just once and have it affect all
516-
repositories you touch.
517-
518-
When the `core.fsmonitor` configuration variable is changed, the
519-
file system monitor is added to or removed from the index the next time
520-
a command reads the index. When `--[no-]fsmonitor` are used, the file
521-
system monitor is immediately added to or removed from the index.
513+
the `core.fsmonitor` or `core.useBuiltinFSMonitor` configuration
514+
variable (see linkgit:git-config[1]) than using the `--fsmonitor`
515+
option to `git update-index` in each repository, especially if you
516+
want to do so across all repositories you use, because you can set the
517+
configuration variable in your `$HOME/.gitconfig` just once and have
518+
it affect all repositories you touch.
519+
520+
When the `core.fsmonitor` or `core.useBuiltinFSMonitor` configuration
521+
variable is changed, the file system monitor is added to or removed
522+
from the index the next time a command reads the index. When
523+
`--[no-]fsmonitor` are used, the file system monitor is immediately
524+
added to or removed from the index.
522525

523526
CONFIGURATION
524527
-------------

Documentation/githooks.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,8 @@ fsmonitor-watchman
593593

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

598599
Version 1 takes two arguments, a version (1) and the time in elapsed
599600
nanoseconds since midnight, January 1, 1970.

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,8 @@ LIB_OBJS += fetch-pack.o
901901
LIB_OBJS += fmt-merge-msg.o
902902
LIB_OBJS += fsck.o
903903
LIB_OBJS += fsmonitor.o
904+
LIB_OBJS += fsmonitor-ipc.o
905+
LIB_OBJS += fsmonitor-settings.o
904906
LIB_OBJS += gettext.o
905907
LIB_OBJS += gpg-interface.o
906908
LIB_OBJS += graph.o

builtin/update-index.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,14 +1220,25 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
12201220
}
12211221

12221222
if (fsmonitor > 0) {
1223-
if (git_config_get_fsmonitor() == 0)
1223+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
1224+
1225+
if (fsm_mode == FSMONITOR_MODE_DISABLED) {
1226+
warning(_("core.useBuiltinFSMonitor is unset; "
1227+
"set it if you really want to enable the "
1228+
"builtin fsmonitor"));
12241229
warning(_("core.fsmonitor is unset; "
1225-
"set it if you really want to "
1226-
"enable fsmonitor"));
1230+
"set it if you really want to enable the "
1231+
"hook-based fsmonitor"));
1232+
}
12271233
add_fsmonitor(&the_index);
12281234
report(_("fsmonitor enabled"));
12291235
} else if (!fsmonitor) {
1230-
if (git_config_get_fsmonitor() == 1)
1236+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
1237+
if (fsm_mode == FSMONITOR_MODE_IPC)
1238+
warning(_("core.useBuiltinFSMonitor is set; "
1239+
"remove it if you really want to "
1240+
"disable fsmonitor"));
1241+
if (fsm_mode == FSMONITOR_MODE_HOOK)
12311242
warning(_("core.fsmonitor is set; "
12321243
"remove it if you really want to "
12331244
"disable fsmonitor"));

cache.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,6 @@ extern int core_preload_index;
996996
extern int precomposed_unicode;
997997
extern int protect_hfs;
998998
extern int protect_ntfs;
999-
extern const char *core_fsmonitor;
1000999

10011000
extern int core_apply_sparse_checkout;
10021001
extern int core_sparse_checkout_cone;

config.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,20 +2510,6 @@ int git_config_get_max_percent_split_change(void)
25102510
return -1; /* default value */
25112511
}
25122512

2513-
int git_config_get_fsmonitor(void)
2514-
{
2515-
if (git_config_get_pathname("core.fsmonitor", &core_fsmonitor))
2516-
core_fsmonitor = getenv("GIT_TEST_FSMONITOR");
2517-
2518-
if (core_fsmonitor && !*core_fsmonitor)
2519-
core_fsmonitor = NULL;
2520-
2521-
if (core_fsmonitor)
2522-
return 1;
2523-
2524-
return 0;
2525-
}
2526-
25272513
int git_config_get_index_threads(int *dest)
25282514
{
25292515
int is_bool, val;

config.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,6 @@ int git_config_get_pathname(const char *key, const char **dest);
611611
int git_config_get_index_threads(int *dest);
612612
int git_config_get_split_index(void);
613613
int git_config_get_max_percent_split_change(void);
614-
int git_config_get_fsmonitor(void);
615614

616615
/* This dies if the configured or default date is in the future */
617616
int git_config_get_expiry(const char *key, const char **output);

environment.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ int protect_hfs = PROTECT_HFS_DEFAULT;
8383
#define PROTECT_NTFS_DEFAULT 1
8484
#endif
8585
int protect_ntfs = PROTECT_NTFS_DEFAULT;
86-
const char *core_fsmonitor;
8786

8887
/*
8988
* The character that begins a commented line in user-editable file

fsmonitor-ipc.c

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#include "cache.h"
2+
#include "fsmonitor.h"
3+
#include "simple-ipc.h"
4+
#include "fsmonitor-ipc.h"
5+
#include "run-command.h"
6+
#include "strbuf.h"
7+
#include "trace2.h"
8+
9+
#ifdef HAVE_FSMONITOR_DAEMON_BACKEND
10+
11+
int fsmonitor_ipc__is_supported(void)
12+
{
13+
return 1;
14+
}
15+
16+
GIT_PATH_FUNC(fsmonitor_ipc__get_path, "fsmonitor--daemon.ipc")
17+
18+
enum ipc_active_state fsmonitor_ipc__get_state(void)
19+
{
20+
return ipc_get_active_state(fsmonitor_ipc__get_path());
21+
}
22+
23+
static int spawn_daemon(void)
24+
{
25+
const char *args[] = { "fsmonitor--daemon", "start", NULL };
26+
27+
return run_command_v_opt_tr2(args, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD,
28+
"fsmonitor");
29+
}
30+
31+
int fsmonitor_ipc__send_query(const char *since_token,
32+
struct strbuf *answer)
33+
{
34+
int ret = -1;
35+
int tried_to_spawn = 0;
36+
enum ipc_active_state state = IPC_STATE__OTHER_ERROR;
37+
struct ipc_client_connection *connection = NULL;
38+
struct ipc_client_connect_options options
39+
= IPC_CLIENT_CONNECT_OPTIONS_INIT;
40+
const char *tok = since_token ? since_token : "";
41+
size_t tok_len = since_token ? strlen(since_token) : 0;
42+
43+
options.wait_if_busy = 1;
44+
options.wait_if_not_found = 0;
45+
46+
trace2_region_enter("fsm_client", "query", NULL);
47+
trace2_data_string("fsm_client", NULL, "query/command", tok);
48+
49+
try_again:
50+
state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options,
51+
&connection);
52+
53+
switch (state) {
54+
case IPC_STATE__LISTENING:
55+
ret = ipc_client_send_command_to_connection(
56+
connection, tok, tok_len, answer);
57+
ipc_client_close_connection(connection);
58+
59+
trace2_data_intmax("fsm_client", NULL,
60+
"query/response-length", answer->len);
61+
62+
if (fsmonitor_is_trivial_response(answer))
63+
trace2_data_intmax("fsm_client", NULL,
64+
"query/trivial-response", 1);
65+
66+
goto done;
67+
68+
case IPC_STATE__NOT_LISTENING:
69+
case IPC_STATE__PATH_NOT_FOUND:
70+
if (tried_to_spawn)
71+
goto done;
72+
73+
tried_to_spawn++;
74+
if (spawn_daemon())
75+
goto done;
76+
77+
/*
78+
* Try again, but this time give the daemon a chance to
79+
* actually create the pipe/socket.
80+
*
81+
* Granted, the daemon just started so it can't possibly have
82+
* any FS cached yet, so we'll always get a trivial answer.
83+
* BUT the answer should include a new token that can serve
84+
* as the basis for subsequent requests.
85+
*/
86+
options.wait_if_not_found = 1;
87+
goto try_again;
88+
89+
case IPC_STATE__INVALID_PATH:
90+
ret = error(_("fsmonitor_ipc__send_query: invalid path '%s'"),
91+
fsmonitor_ipc__get_path());
92+
goto done;
93+
94+
case IPC_STATE__OTHER_ERROR:
95+
default:
96+
ret = error(_("fsmonitor_ipc__send_query: unspecified error on '%s'"),
97+
fsmonitor_ipc__get_path());
98+
goto done;
99+
}
100+
101+
done:
102+
trace2_region_leave("fsm_client", "query", NULL);
103+
104+
return ret;
105+
}
106+
107+
int fsmonitor_ipc__send_command(const char *command,
108+
struct strbuf *answer)
109+
{
110+
struct ipc_client_connection *connection = NULL;
111+
struct ipc_client_connect_options options
112+
= IPC_CLIENT_CONNECT_OPTIONS_INIT;
113+
int ret;
114+
enum ipc_active_state state;
115+
const char *c = command ? command : "";
116+
size_t c_len = command ? strlen(command) : 0;
117+
118+
strbuf_reset(answer);
119+
120+
options.wait_if_busy = 1;
121+
options.wait_if_not_found = 0;
122+
123+
state = ipc_client_try_connect(fsmonitor_ipc__get_path(), &options,
124+
&connection);
125+
if (state != IPC_STATE__LISTENING) {
126+
die("fsmonitor--daemon is not running");
127+
return -1;
128+
}
129+
130+
ret = ipc_client_send_command_to_connection(connection, c, c_len,
131+
answer);
132+
ipc_client_close_connection(connection);
133+
134+
if (ret == -1) {
135+
die("could not send '%s' command to fsmonitor--daemon", c);
136+
return -1;
137+
}
138+
139+
return 0;
140+
}
141+
142+
#else
143+
144+
/*
145+
* A trivial implementation of the fsmonitor_ipc__ API for unsupported
146+
* platforms.
147+
*/
148+
149+
int fsmonitor_ipc__is_supported(void)
150+
{
151+
return 0;
152+
}
153+
154+
const char *fsmonitor_ipc__get_path(void)
155+
{
156+
return NULL;
157+
}
158+
159+
enum ipc_active_state fsmonitor_ipc__get_state(void)
160+
{
161+
return IPC_STATE__OTHER_ERROR;
162+
}
163+
164+
int fsmonitor_ipc__send_query(const char *since_token,
165+
struct strbuf *answer)
166+
{
167+
return -1;
168+
}
169+
170+
int fsmonitor_ipc__send_command(const char *command,
171+
struct strbuf *answer)
172+
{
173+
return -1;
174+
}
175+
176+
#endif

0 commit comments

Comments
 (0)