Skip to content

Commit abbc910

Browse files
jeffhostetlergitster
authored andcommitted
fsmonitor-settings: bare repos are incompatible with FSMonitor
Bare repos do not have a worktree, so there is nothing for the daemon watch. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 5339287 commit abbc910

File tree

5 files changed

+105
-0
lines changed

5 files changed

+105
-0
lines changed

builtin/fsmonitor--daemon.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,12 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
14491449
die(_("invalid 'ipc-threads' value (%d)"),
14501450
fsmonitor__ipc_threads);
14511451

1452+
prepare_repo_settings(the_repository);
1453+
fsm_settings__set_ipc(the_repository);
1454+
1455+
if (fsm_settings__error_if_incompatible(the_repository))
1456+
return 1;
1457+
14521458
if (!strcmp(subcmd, "start"))
14531459
return !!try_to_start_background_daemon();
14541460

builtin/update-index.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,10 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
12371237

12381238
if (fsmonitor > 0) {
12391239
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
1240+
1241+
if (fsm_settings__error_if_incompatible(the_repository))
1242+
return 1;
1243+
12401244
if (fsm_mode == FSMONITOR_MODE_DISABLED) {
12411245
warning(_("core.fsmonitor is unset; "
12421246
"set it if you really want to "

fsmonitor-settings.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,33 @@
99
*/
1010
struct fsmonitor_settings {
1111
enum fsmonitor_mode mode;
12+
enum fsmonitor_reason reason;
1213
char *hook_path;
1314
};
1415

16+
static void set_incompatible(struct repository *r,
17+
enum fsmonitor_reason reason)
18+
{
19+
struct fsmonitor_settings *s = r->settings.fsmonitor;
20+
21+
s->mode = FSMONITOR_MODE_INCOMPATIBLE;
22+
s->reason = reason;
23+
}
24+
25+
static int check_for_incompatible(struct repository *r)
26+
{
27+
if (!r->worktree) {
28+
/*
29+
* Bare repositories don't have a working directory and
30+
* therefore have nothing to watch.
31+
*/
32+
set_incompatible(r, FSMONITOR_REASON_BARE);
33+
return 1;
34+
}
35+
36+
return 0;
37+
}
38+
1539
static void lookup_fsmonitor_settings(struct repository *r)
1640
{
1741
struct fsmonitor_settings *s;
@@ -23,6 +47,7 @@ static void lookup_fsmonitor_settings(struct repository *r)
2347

2448
CALLOC_ARRAY(s, 1);
2549
s->mode = FSMONITOR_MODE_DISABLED;
50+
s->reason = FSMONITOR_REASON_OK;
2651

2752
r->settings.fsmonitor = s;
2853

@@ -86,6 +111,9 @@ void fsm_settings__set_ipc(struct repository *r)
86111

87112
lookup_fsmonitor_settings(r);
88113

114+
if (check_for_incompatible(r))
115+
return;
116+
89117
r->settings.fsmonitor->mode = FSMONITOR_MODE_IPC;
90118
FREE_AND_NULL(r->settings.fsmonitor->hook_path);
91119
}
@@ -97,6 +125,9 @@ void fsm_settings__set_hook(struct repository *r, const char *path)
97125

98126
lookup_fsmonitor_settings(r);
99127

128+
if (check_for_incompatible(r))
129+
return;
130+
100131
r->settings.fsmonitor->mode = FSMONITOR_MODE_HOOK;
101132
FREE_AND_NULL(r->settings.fsmonitor->hook_path);
102133
r->settings.fsmonitor->hook_path = strdup(path);
@@ -110,5 +141,34 @@ void fsm_settings__set_disabled(struct repository *r)
110141
lookup_fsmonitor_settings(r);
111142

112143
r->settings.fsmonitor->mode = FSMONITOR_MODE_DISABLED;
144+
r->settings.fsmonitor->reason = FSMONITOR_REASON_OK;
113145
FREE_AND_NULL(r->settings.fsmonitor->hook_path);
114146
}
147+
148+
enum fsmonitor_reason fsm_settings__get_reason(struct repository *r)
149+
{
150+
if (!r)
151+
r = the_repository;
152+
153+
lookup_fsmonitor_settings(r);
154+
155+
return r->settings.fsmonitor->reason;
156+
}
157+
158+
int fsm_settings__error_if_incompatible(struct repository *r)
159+
{
160+
enum fsmonitor_reason reason = fsm_settings__get_reason(r);
161+
162+
switch (reason) {
163+
case FSMONITOR_REASON_OK:
164+
return 0;
165+
166+
case FSMONITOR_REASON_BARE:
167+
error(_("bare repository '%s' is incompatible with fsmonitor"),
168+
xgetcwd());
169+
return 1;
170+
}
171+
172+
BUG("Unhandled case in fsm_settings__error_if_incompatible: '%d'",
173+
reason);
174+
}

fsmonitor-settings.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,30 @@
44
struct repository;
55

66
enum fsmonitor_mode {
7+
FSMONITOR_MODE_INCOMPATIBLE = -1, /* see _reason */
78
FSMONITOR_MODE_DISABLED = 0,
89
FSMONITOR_MODE_HOOK = 1, /* core.fsmonitor=<hook_path> */
910
FSMONITOR_MODE_IPC = 2, /* core.fsmonitor=<true> */
1011
};
1112

13+
/*
14+
* Incompatibility reasons.
15+
*/
16+
enum fsmonitor_reason {
17+
FSMONITOR_REASON_OK = 0, /* no incompatibility or when disbled */
18+
FSMONITOR_REASON_BARE,
19+
};
20+
1221
void fsm_settings__set_ipc(struct repository *r);
1322
void fsm_settings__set_hook(struct repository *r, const char *path);
1423
void fsm_settings__set_disabled(struct repository *r);
1524

1625
enum fsmonitor_mode fsm_settings__get_mode(struct repository *r);
1726
const char *fsm_settings__get_hook_path(struct repository *r);
1827

28+
enum fsmonitor_reason fsm_settings__get_reason(struct repository *r);
29+
int fsm_settings__error_if_incompatible(struct repository *r);
30+
1931
struct fsmonitor_settings;
2032

2133
#endif /* FSMONITOR_SETTINGS_H */

t/t7519-status-fsmonitor.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,29 @@ test_lazy_prereq UNTRACKED_CACHE '
5555
test $ret -ne 1
5656
'
5757

58+
# Test that we detect and disallow repos that are incompatible with FSMonitor.
59+
test_expect_success 'incompatible bare repo' '
60+
test_when_finished "rm -rf ./bare-clone actual expect" &&
61+
git init --bare bare-clone &&
62+
63+
test_must_fail \
64+
git -C ./bare-clone -c core.fsmonitor=foo \
65+
update-index --fsmonitor 2>actual &&
66+
grep "bare repository .* is incompatible with fsmonitor" actual &&
67+
68+
test_must_fail \
69+
git -C ./bare-clone -c core.fsmonitor=true \
70+
update-index --fsmonitor 2>actual &&
71+
grep "bare repository .* is incompatible with fsmonitor" actual
72+
'
73+
74+
test_expect_success FSMONITOR_DAEMON 'run fsmonitor-daemon in bare repo' '
75+
test_when_finished "rm -rf ./bare-clone actual" &&
76+
git init --bare bare-clone &&
77+
test_must_fail git -C ./bare-clone fsmonitor--daemon run 2>actual &&
78+
grep "bare repository .* is incompatible with fsmonitor" actual
79+
'
80+
5881
test_expect_success 'setup' '
5982
mkdir -p .git/hooks &&
6083
: >tracked &&

0 commit comments

Comments
 (0)