Skip to content

Commit 4cc3417

Browse files
jeffhostetlerdscho
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 <[email protected]>
1 parent a2dd981 commit 4cc3417

File tree

5 files changed

+130
-9
lines changed

5 files changed

+130
-9
lines changed

builtin/fsmonitor--daemon.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,17 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
14241424
die(_("invalid 'ipc-threads' value (%d)"),
14251425
fsmonitor__ipc_threads);
14261426

1427+
prepare_repo_settings(the_repository);
1428+
fsm_settings__set_ipc(the_repository);
1429+
1430+
if (fsm_settings__get_mode(the_repository) == FSMONITOR_MODE_INCOMPATIBLE) {
1431+
struct strbuf buf_reason = STRBUF_INIT;
1432+
fsm_settings__get_reason(the_repository, &buf_reason);
1433+
error("%s '%s'", buf_reason.buf, xgetcwd());
1434+
strbuf_release(&buf_reason);
1435+
return -1;
1436+
}
1437+
14271438
if (!strcmp(subcmd, "start"))
14281439
return !!try_to_start_background_daemon();
14291440

builtin/update-index.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,14 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
12161216
if (fsmonitor > 0) {
12171217
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
12181218

1219+
if (fsm_mode == FSMONITOR_MODE_INCOMPATIBLE) {
1220+
struct strbuf buf_reason = STRBUF_INIT;
1221+
fsm_settings__get_reason(r, &buf_reason);
1222+
error("%s", buf_reason.buf);
1223+
strbuf_release(&buf_reason);
1224+
return -1;
1225+
}
1226+
12191227
if (fsm_mode == FSMONITOR_MODE_DISABLED) {
12201228
warning(_("core.useBuiltinFSMonitor is unset; "
12211229
"set it if you really want to enable the "

fsmonitor-settings.c

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

15-
void fsm_settings__set_ipc(struct repository *r)
16+
static void set_incompatible(struct repository *r,
17+
enum fsmonitor_reason reason)
1618
{
1719
struct fsmonitor_settings *s = r->settings.fsmonitor;
1820

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+
39+
static struct fsmonitor_settings *s_init(struct repository *r)
40+
{
41+
if (!r->settings.fsmonitor)
42+
CALLOC_ARRAY(r->settings.fsmonitor, 1);
43+
44+
return r->settings.fsmonitor;
45+
}
46+
47+
void fsm_settings__set_ipc(struct repository *r)
48+
{
49+
struct fsmonitor_settings *s = s_init(r);
50+
51+
if (check_for_incompatible(r))
52+
return;
53+
1954
s->mode = FSMONITOR_MODE_IPC;
2055
}
2156

2257
void fsm_settings__set_hook(struct repository *r, const char *path)
2358
{
24-
struct fsmonitor_settings *s = r->settings.fsmonitor;
59+
struct fsmonitor_settings *s = s_init(r);
60+
61+
if (check_for_incompatible(r))
62+
return;
2563

2664
s->mode = FSMONITOR_MODE_HOOK;
2765
s->hook_path = strdup(path);
2866
}
2967

3068
void fsm_settings__set_disabled(struct repository *r)
3169
{
32-
struct fsmonitor_settings *s = r->settings.fsmonitor;
70+
struct fsmonitor_settings *s = s_init(r);
3371

3472
s->mode = FSMONITOR_MODE_DISABLED;
73+
s->reason = FSMONITOR_REASON_ZERO;
3574
FREE_AND_NULL(s->hook_path);
3675
}
3776

@@ -65,12 +104,6 @@ static int check_for_hook(struct repository *r)
65104

66105
static void lookup_fsmonitor_settings(struct repository *r)
67106
{
68-
struct fsmonitor_settings *s;
69-
70-
CALLOC_ARRAY(s, 1);
71-
72-
r->settings.fsmonitor = s;
73-
74107
if (check_for_ipc(r))
75108
return;
76109

@@ -95,3 +128,35 @@ const char *fsm_settings__get_hook_path(struct repository *r)
95128

96129
return r->settings.fsmonitor->hook_path;
97130
}
131+
132+
static void create_reason_message(struct repository *r,
133+
struct strbuf *buf_reason)
134+
{
135+
struct fsmonitor_settings *s = r->settings.fsmonitor;
136+
137+
switch (s->reason) {
138+
case FSMONITOR_REASON_ZERO:
139+
return;
140+
141+
case FSMONITOR_REASON_BARE:
142+
strbuf_addstr(buf_reason,
143+
_("bare repos are incompatible with fsmonitor"));
144+
return;
145+
146+
default:
147+
BUG("Unhandled case in create_reason_message '%d'", s->reason);
148+
}
149+
}
150+
enum fsmonitor_reason fsm_settings__get_reason(struct repository *r,
151+
struct strbuf *buf_reason)
152+
{
153+
strbuf_reset(buf_reason);
154+
155+
if (!r->settings.fsmonitor)
156+
lookup_fsmonitor_settings(r);
157+
158+
if (r->settings.fsmonitor->mode == FSMONITOR_MODE_INCOMPATIBLE)
159+
create_reason_message(r, buf_reason);
160+
161+
return r->settings.fsmonitor->reason;
162+
}

fsmonitor-settings.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@
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 */
910
FSMONITOR_MODE_IPC = 2, /* core.useBuiltinFSMonitor */
1011
};
1112

13+
/*
14+
* Incompatibility reasons.
15+
*/
16+
enum fsmonitor_reason {
17+
FSMONITOR_REASON_ZERO = 0,
18+
FSMONITOR_REASON_BARE = 1,
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);
27+
enum fsmonitor_reason fsm_settings__get_reason(struct repository *r,
28+
struct strbuf *buf_reason);
1829

1930
struct fsmonitor_settings;
2031

t/t7519-status-fsmonitor.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,32 @@ 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+
cat >expect <<-\EOF &&
63+
error: bare repos are incompatible with fsmonitor
64+
EOF
65+
66+
test_must_fail \
67+
git -C ./bare-clone -c core.fsmonitor=foo \
68+
update-index --fsmonitor 2>actual &&
69+
test_cmp expect actual &&
70+
71+
test_must_fail \
72+
git -C ./bare-clone -c core.usebuiltinfsmonitor=true \
73+
update-index --fsmonitor 2>actual &&
74+
test_cmp expect actual
75+
'
76+
77+
test_expect_success FSMONITOR_DAEMON 'run fsmonitor-daemon in bare repo' '
78+
test_when_finished "rm -rf ./bare-clone actual" &&
79+
git init --bare bare-clone &&
80+
test_must_fail git -C ./bare-clone fsmonitor--daemon run 2>actual &&
81+
grep "bare repos are incompatible with fsmonitor" actual
82+
'
83+
5884
test_expect_success 'setup' '
5985
mkdir -p .git/hooks &&
6086
: >tracked &&

0 commit comments

Comments
 (0)