Skip to content

Commit 0a756b2

Browse files
committed
fsmonitor: config settings are repository-specific
Move FSMonitor config settings to a new `struct fsmonitor_settings` structure. Add a lazily-loaded pointer to `struct repo_settings`. Create `fsm_settings__get_*()` getters to lazily look up fsmonitor- related config settings. Get rid of the `core_fsmonitor` global variable, and add support for the new `core.useBuiltinFSMonitor` config setting. Move config code to lookup the existing `core.fsmonitor` value to `fsmonitor-settings.[ch]`. The `core_fsmonitor` global variable was used to store the pathname to the FSMonitor hook and it was used as a boolean to see if FSMonitor was enabled. This dual usage will lead to confusion when we add support for a builtin FSMonitor based on IPC, since the builtin FSMonitor doesn't need the hook pathname. Replace the boolean usage with an `enum fsmonitor_mode` to represent the state of FSMonitor. And only set the pathname when in HOOK mode. Signed-off-by: Jeff Hostetler <[email protected]>
1 parent 0aaca2f commit 0a756b2

13 files changed

+194
-51
lines changed

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,7 @@ LIB_OBJS += fmt-merge-msg.o
894894
LIB_OBJS += fsck.o
895895
LIB_OBJS += fsmonitor.o
896896
LIB_OBJS += fsmonitor-ipc.o
897+
LIB_OBJS += fsmonitor-settings.o
897898
LIB_OBJS += gettext.o
898899
LIB_OBJS += gpg-interface.o
899900
LIB_OBJS += graph.o

builtin/update-index.c

+15-4
Original file line numberDiff line numberDiff line change
@@ -1216,14 +1216,25 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
12161216
}
12171217

12181218
if (fsmonitor > 0) {
1219-
if (git_config_get_fsmonitor() == 0)
1219+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
1220+
1221+
if (fsm_mode == FSMONITOR_MODE_DISABLED) {
1222+
warning(_("core.useBuiltinFSMonitor is unset; "
1223+
"set it if you really want to enable the "
1224+
"builtin fsmonitor"));
12201225
warning(_("core.fsmonitor is unset; "
1221-
"set it if you really want to "
1222-
"enable fsmonitor"));
1226+
"set it if you really want to enable the "
1227+
"hook-based fsmonitor"));
1228+
}
12231229
add_fsmonitor(&the_index);
12241230
report(_("fsmonitor enabled"));
12251231
} else if (!fsmonitor) {
1226-
if (git_config_get_fsmonitor() == 1)
1232+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
1233+
if (fsm_mode == FSMONITOR_MODE_IPC)
1234+
warning(_("core.useBuiltinFSMonitor is set; "
1235+
"remove it if you really want to "
1236+
"disable fsmonitor"));
1237+
if (fsm_mode == FSMONITOR_MODE_HOOK)
12271238
warning(_("core.fsmonitor is set; "
12281239
"remove it if you really want to "
12291240
"disable fsmonitor"));

cache.h

-1
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,6 @@ extern int core_preload_index;
981981
extern int precomposed_unicode;
982982
extern int protect_hfs;
983983
extern int protect_ntfs;
984-
extern const char *core_fsmonitor;
985984

986985
extern int core_apply_sparse_checkout;
987986
extern int core_sparse_checkout_cone;

config.c

-14
Original file line numberDiff line numberDiff line change
@@ -2516,20 +2516,6 @@ int git_config_get_max_percent_split_change(void)
25162516
return -1; /* default value */
25172517
}
25182518

2519-
int git_config_get_fsmonitor(void)
2520-
{
2521-
if (git_config_get_pathname("core.fsmonitor", &core_fsmonitor))
2522-
core_fsmonitor = getenv("GIT_TEST_FSMONITOR");
2523-
2524-
if (core_fsmonitor && !*core_fsmonitor)
2525-
core_fsmonitor = NULL;
2526-
2527-
if (core_fsmonitor)
2528-
return 1;
2529-
2530-
return 0;
2531-
}
2532-
25332519
int git_config_get_index_threads(int *dest)
25342520
{
25352521
int is_bool, val;

config.h

-1
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,6 @@ int git_config_get_index_threads(int *dest);
609609
int git_config_get_untracked_cache(void);
610610
int git_config_get_split_index(void);
611611
int git_config_get_max_percent_split_change(void);
612-
int git_config_get_fsmonitor(void);
613612

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

environment.c

-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ int protect_hfs = PROTECT_HFS_DEFAULT;
8484
#define PROTECT_NTFS_DEFAULT 1
8585
#endif
8686
int protect_ntfs = PROTECT_NTFS_DEFAULT;
87-
const char *core_fsmonitor;
8887

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

fsmonitor-settings.c

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include "cache.h"
2+
#include "config.h"
3+
#include "repository.h"
4+
#include "fsmonitor-settings.h"
5+
6+
/*
7+
* We keep this structure defintion private and have getters
8+
* for all fields so that we can lazy load it as needed.
9+
*/
10+
struct fsmonitor_settings {
11+
enum fsmonitor_mode mode;
12+
char *hook_path;
13+
};
14+
15+
void fsm_settings__set_ipc(struct repository *r)
16+
{
17+
struct fsmonitor_settings *s = r->settings.fsmonitor;
18+
19+
s->mode = FSMONITOR_MODE_IPC;
20+
}
21+
22+
void fsm_settings__set_hook(struct repository *r, const char *path)
23+
{
24+
struct fsmonitor_settings *s = r->settings.fsmonitor;
25+
26+
s->mode = FSMONITOR_MODE_HOOK;
27+
s->hook_path = strdup(path);
28+
}
29+
30+
void fsm_settings__set_disabled(struct repository *r)
31+
{
32+
struct fsmonitor_settings *s = r->settings.fsmonitor;
33+
34+
s->mode = FSMONITOR_MODE_DISABLED;
35+
FREE_AND_NULL(s->hook_path);
36+
}
37+
38+
static int check_for_ipc(struct repository *r)
39+
{
40+
int value;
41+
42+
if (!repo_config_get_bool(r, "core.usebuiltinfsmonitor", &value) &&
43+
value) {
44+
fsm_settings__set_ipc(r);
45+
return 1;
46+
}
47+
48+
return 0;
49+
}
50+
51+
static int check_for_hook(struct repository *r)
52+
{
53+
const char *const_str;
54+
55+
if (repo_config_get_pathname(r, "core.fsmonitor", &const_str))
56+
const_str = getenv("GIT_TEST_FSMONITOR");
57+
58+
if (const_str && *const_str) {
59+
fsm_settings__set_hook(r, const_str);
60+
return 1;
61+
}
62+
63+
return 0;
64+
}
65+
66+
static void lookup_fsmonitor_settings(struct repository *r)
67+
{
68+
struct fsmonitor_settings *s;
69+
70+
CALLOC_ARRAY(s, 1);
71+
72+
r->settings.fsmonitor = s;
73+
74+
if (check_for_ipc(r))
75+
return;
76+
77+
if (check_for_hook(r))
78+
return;
79+
80+
fsm_settings__set_disabled(r);
81+
}
82+
83+
enum fsmonitor_mode fsm_settings__get_mode(struct repository *r)
84+
{
85+
if (!r->settings.fsmonitor)
86+
lookup_fsmonitor_settings(r);
87+
88+
return r->settings.fsmonitor->mode;
89+
}
90+
91+
const char *fsm_settings__get_hook_path(struct repository *r)
92+
{
93+
if (!r->settings.fsmonitor)
94+
lookup_fsmonitor_settings(r);
95+
96+
return r->settings.fsmonitor->hook_path;
97+
}

fsmonitor-settings.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef FSMONITOR_SETTINGS_H
2+
#define FSMONITOR_SETTINGS_H
3+
4+
struct repository;
5+
6+
enum fsmonitor_mode {
7+
FSMONITOR_MODE_DISABLED = 0,
8+
FSMONITOR_MODE_HOOK = 1, /* core.fsmonitor */
9+
FSMONITOR_MODE_IPC = 2, /* core.useBuiltinFSMonitor */
10+
};
11+
12+
void fsm_settings__set_ipc(struct repository *r);
13+
void fsm_settings__set_hook(struct repository *r, const char *path);
14+
void fsm_settings__set_disabled(struct repository *r);
15+
16+
enum fsmonitor_mode fsm_settings__get_mode(struct repository *r);
17+
const char *fsm_settings__get_hook_path(struct repository *r);
18+
19+
struct fsmonitor_settings;
20+
21+
#endif /* FSMONITOR_SETTINGS_H */

fsmonitor.c

+38-25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "dir.h"
44
#include "ewah/ewok.h"
55
#include "fsmonitor.h"
6+
#include "fsmonitor-ipc.h"
67
#include "run-command.h"
78
#include "strbuf.h"
89

@@ -148,15 +149,18 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
148149
/*
149150
* Call the query-fsmonitor hook passing the last update token of the saved results.
150151
*/
151-
static int query_fsmonitor(int version, const char *last_update, struct strbuf *query_result)
152+
static int query_fsmonitor_hook(struct repository *r,
153+
int version,
154+
const char *last_update,
155+
struct strbuf *query_result)
152156
{
153157
struct child_process cp = CHILD_PROCESS_INIT;
154158
int result;
155159

156-
if (!core_fsmonitor)
160+
if (fsm_settings__get_mode(r) != FSMONITOR_MODE_HOOK)
157161
return -1;
158162

159-
strvec_push(&cp.args, core_fsmonitor);
163+
strvec_push(&cp.args, fsm_settings__get_hook_path(r));
160164
strvec_pushf(&cp.args, "%d", version);
161165
strvec_pushf(&cp.args, "%s", last_update);
162166
cp.use_shell = 1;
@@ -238,31 +242,43 @@ void refresh_fsmonitor(struct index_state *istate)
238242
struct strbuf last_update_token = STRBUF_INIT;
239243
char *buf;
240244
unsigned int i;
245+
struct repository *r = istate->repo ? istate->repo : the_repository;
246+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
241247

242-
if (!core_fsmonitor || istate->fsmonitor_has_run_once)
248+
if (fsm_mode <= FSMONITOR_MODE_DISABLED ||
249+
istate->fsmonitor_has_run_once)
243250
return;
244251

245-
hook_version = fsmonitor_hook_version();
246-
247252
istate->fsmonitor_has_run_once = 1;
248253

249254
trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
255+
256+
if (fsm_mode == FSMONITOR_MODE_IPC) {
257+
/* TODO */
258+
return;
259+
}
260+
261+
assert(fsm_mode == FSMONITOR_MODE_HOOK);
262+
263+
hook_version = fsmonitor_hook_version();
264+
250265
/*
251-
* This could be racy so save the date/time now and query_fsmonitor
266+
* This could be racy so save the date/time now and query_fsmonitor_hook
252267
* should be inclusive to ensure we don't miss potential changes.
253268
*/
254269
last_update = getnanotime();
255270
if (hook_version == HOOK_INTERFACE_VERSION1)
256271
strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
257272

258273
/*
259-
* If we have a last update token, call query_fsmonitor for the set of
274+
* If we have a last update token, call query_fsmonitor_hook for the set of
260275
* changes since that token, else assume everything is possibly dirty
261276
* and check it all.
262277
*/
263278
if (istate->fsmonitor_last_update) {
264279
if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {
265-
query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION2,
280+
query_success = !query_fsmonitor_hook(
281+
r, HOOK_INTERFACE_VERSION2,
266282
istate->fsmonitor_last_update, &query_result);
267283

268284
if (query_success) {
@@ -292,13 +308,17 @@ void refresh_fsmonitor(struct index_state *istate)
292308
}
293309

294310
if (hook_version == HOOK_INTERFACE_VERSION1) {
295-
query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION1,
311+
query_success = !query_fsmonitor_hook(
312+
r, HOOK_INTERFACE_VERSION1,
296313
istate->fsmonitor_last_update, &query_result);
297314
}
298315

299-
trace_performance_since(last_update, "fsmonitor process '%s'", core_fsmonitor);
300-
trace_printf_key(&trace_fsmonitor, "fsmonitor process '%s' returned %s",
301-
core_fsmonitor, query_success ? "success" : "failure");
316+
trace_performance_since(last_update, "fsmonitor process '%s'",
317+
fsm_settings__get_hook_path(r));
318+
trace_printf_key(&trace_fsmonitor,
319+
"fsmonitor process '%s' returned %s",
320+
fsm_settings__get_hook_path(r),
321+
query_success ? "success" : "failure");
302322
}
303323

304324
/* a fsmonitor process can return '/' to indicate all entries are invalid */
@@ -411,7 +431,8 @@ void remove_fsmonitor(struct index_state *istate)
411431
void tweak_fsmonitor(struct index_state *istate)
412432
{
413433
unsigned int i;
414-
int fsmonitor_enabled = git_config_get_fsmonitor();
434+
struct repository *r = istate->repo ? istate->repo : the_repository;
435+
int fsmonitor_enabled = (fsm_settings__get_mode(r) > FSMONITOR_MODE_DISABLED);
415436

416437
if (istate->fsmonitor_dirty) {
417438
if (fsmonitor_enabled) {
@@ -431,16 +452,8 @@ void tweak_fsmonitor(struct index_state *istate)
431452
istate->fsmonitor_dirty = NULL;
432453
}
433454

434-
switch (fsmonitor_enabled) {
435-
case -1: /* keep: do nothing */
436-
break;
437-
case 0: /* false */
438-
remove_fsmonitor(istate);
439-
break;
440-
case 1: /* true */
455+
if (fsmonitor_enabled)
441456
add_fsmonitor(istate);
442-
break;
443-
default: /* unknown value: do nothing */
444-
break;
445-
}
457+
else
458+
remove_fsmonitor(istate);
446459
}

fsmonitor.h

+15-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "cache.h"
55
#include "dir.h"
6+
#include "fsmonitor-settings.h"
67

78
extern struct trace_key trace_fsmonitor;
89

@@ -57,7 +58,11 @@ int fsmonitor_is_trivial_response(const struct strbuf *query_result);
5758
*/
5859
static inline int is_fsmonitor_refreshed(const struct index_state *istate)
5960
{
60-
return !core_fsmonitor || istate->fsmonitor_has_run_once;
61+
struct repository *r = istate->repo ? istate->repo : the_repository;
62+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
63+
64+
return fsm_mode <= FSMONITOR_MODE_DISABLED ||
65+
istate->fsmonitor_has_run_once;
6166
}
6267

6368
/*
@@ -67,7 +72,11 @@ static inline int is_fsmonitor_refreshed(const struct index_state *istate)
6772
*/
6873
static inline void mark_fsmonitor_valid(struct index_state *istate, struct cache_entry *ce)
6974
{
70-
if (core_fsmonitor && !(ce->ce_flags & CE_FSMONITOR_VALID)) {
75+
struct repository *r = istate->repo ? istate->repo : the_repository;
76+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
77+
78+
if (fsm_mode > FSMONITOR_MODE_DISABLED &&
79+
!(ce->ce_flags & CE_FSMONITOR_VALID)) {
7180
istate->cache_changed = 1;
7281
ce->ce_flags |= CE_FSMONITOR_VALID;
7382
trace_printf_key(&trace_fsmonitor, "mark_fsmonitor_clean '%s'", ce->name);
@@ -83,7 +92,10 @@ static inline void mark_fsmonitor_valid(struct index_state *istate, struct cache
8392
*/
8493
static inline void mark_fsmonitor_invalid(struct index_state *istate, struct cache_entry *ce)
8594
{
86-
if (core_fsmonitor) {
95+
struct repository *r = istate->repo ? istate->repo : the_repository;
96+
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
97+
98+
if (fsm_mode > FSMONITOR_MODE_DISABLED) {
8799
ce->ce_flags &= ~CE_FSMONITOR_VALID;
88100
untracked_cache_invalidate_path(istate, ce->name, 1);
89101
trace_printf_key(&trace_fsmonitor, "mark_fsmonitor_invalid '%s'", ce->name);

repo-settings.c

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ void prepare_repo_settings(struct repository *r)
2626
UPDATE_DEFAULT_BOOL(r->settings.commit_graph_read_changed_paths, 1);
2727
UPDATE_DEFAULT_BOOL(r->settings.gc_write_commit_graph, 1);
2828

29+
r->settings.fsmonitor = NULL; /* lazy loaded */
30+
2931
if (!repo_config_get_int(r, "index.version", &value))
3032
r->settings.index_version = value;
3133
if (!repo_config_get_maybe_bool(r, "core.untrackedcache", &value)) {

0 commit comments

Comments
 (0)