]>
Commit | Line | Data |
---|---|---|
1e0ea5c4 JH |
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; | |
62a62a28 | 12 | enum fsmonitor_reason reason; |
1e0ea5c4 JH |
13 | char *hook_path; |
14 | }; | |
15 | ||
62a62a28 JH |
16 | static enum fsmonitor_reason check_for_incompatible(struct repository *r) |
17 | { | |
18 | if (!r->worktree) { | |
19 | /* | |
20 | * Bare repositories don't have a working directory and | |
21 | * therefore have nothing to watch. | |
22 | */ | |
23 | return FSMONITOR_REASON_BARE; | |
24 | } | |
25 | ||
d33c804d JH |
26 | #ifdef HAVE_FSMONITOR_OS_SETTINGS |
27 | { | |
28 | enum fsmonitor_reason reason; | |
29 | ||
30 | reason = fsm_os__incompatible(r); | |
31 | if (reason != FSMONITOR_REASON_OK) | |
32 | return reason; | |
33 | } | |
34 | #endif | |
35 | ||
62a62a28 JH |
36 | return FSMONITOR_REASON_OK; |
37 | } | |
38 | ||
39 | static struct fsmonitor_settings *alloc_settings(void) | |
1e0ea5c4 JH |
40 | { |
41 | struct fsmonitor_settings *s; | |
62a62a28 JH |
42 | |
43 | CALLOC_ARRAY(s, 1); | |
44 | s->mode = FSMONITOR_MODE_DISABLED; | |
45 | s->reason = FSMONITOR_REASON_UNTESTED; | |
46 | ||
47 | return s; | |
48 | } | |
49 | ||
50 | static void lookup_fsmonitor_settings(struct repository *r) | |
51 | { | |
1e0ea5c4 JH |
52 | const char *const_str; |
53 | int bool_value; | |
54 | ||
55 | if (r->settings.fsmonitor) | |
56 | return; | |
57 | ||
1e0ea5c4 JH |
58 | /* |
59 | * Overload the existing "core.fsmonitor" config setting (which | |
60 | * has historically been either unset or a hook pathname) to | |
61 | * now allow a boolean value to enable the builtin FSMonitor | |
62 | * or to turn everything off. (This does imply that you can't | |
63 | * use a hook script named "true" or "false", but that's OK.) | |
64 | */ | |
65 | switch (repo_config_get_maybe_bool(r, "core.fsmonitor", &bool_value)) { | |
66 | ||
67 | case 0: /* config value was set to <bool> */ | |
68 | if (bool_value) | |
69 | fsm_settings__set_ipc(r); | |
62a62a28 JH |
70 | else |
71 | fsm_settings__set_disabled(r); | |
1e0ea5c4 JH |
72 | return; |
73 | ||
74 | case 1: /* config value was unset */ | |
75 | const_str = getenv("GIT_TEST_FSMONITOR"); | |
76 | break; | |
77 | ||
78 | case -1: /* config value set to an arbitrary string */ | |
79 | if (repo_config_get_pathname(r, "core.fsmonitor", &const_str)) | |
80 | return; /* should not happen */ | |
81 | break; | |
82 | ||
83 | default: /* should not happen */ | |
84 | return; | |
85 | } | |
86 | ||
62a62a28 JH |
87 | if (const_str && *const_str) |
88 | fsm_settings__set_hook(r, const_str); | |
89 | else | |
90 | fsm_settings__set_disabled(r); | |
1e0ea5c4 JH |
91 | } |
92 | ||
93 | enum fsmonitor_mode fsm_settings__get_mode(struct repository *r) | |
94 | { | |
95 | if (!r) | |
96 | r = the_repository; | |
62a62a28 JH |
97 | if (!r->settings.fsmonitor) |
98 | lookup_fsmonitor_settings(r); | |
1e0ea5c4 JH |
99 | |
100 | return r->settings.fsmonitor->mode; | |
101 | } | |
102 | ||
103 | const char *fsm_settings__get_hook_path(struct repository *r) | |
104 | { | |
105 | if (!r) | |
106 | r = the_repository; | |
62a62a28 JH |
107 | if (!r->settings.fsmonitor) |
108 | lookup_fsmonitor_settings(r); | |
1e0ea5c4 JH |
109 | |
110 | return r->settings.fsmonitor->hook_path; | |
111 | } | |
112 | ||
113 | void fsm_settings__set_ipc(struct repository *r) | |
114 | { | |
62a62a28 JH |
115 | enum fsmonitor_reason reason = check_for_incompatible(r); |
116 | ||
117 | if (reason != FSMONITOR_REASON_OK) { | |
118 | fsm_settings__set_incompatible(r, reason); | |
119 | return; | |
120 | } | |
121 | ||
122 | /* | |
123 | * Caller requested IPC explicitly, so avoid (possibly | |
124 | * recursive) config lookup. | |
125 | */ | |
1e0ea5c4 JH |
126 | if (!r) |
127 | r = the_repository; | |
62a62a28 JH |
128 | if (!r->settings.fsmonitor) |
129 | r->settings.fsmonitor = alloc_settings(); | |
1e0ea5c4 JH |
130 | |
131 | r->settings.fsmonitor->mode = FSMONITOR_MODE_IPC; | |
62a62a28 | 132 | r->settings.fsmonitor->reason = reason; |
1e0ea5c4 JH |
133 | FREE_AND_NULL(r->settings.fsmonitor->hook_path); |
134 | } | |
135 | ||
136 | void fsm_settings__set_hook(struct repository *r, const char *path) | |
137 | { | |
62a62a28 JH |
138 | enum fsmonitor_reason reason = check_for_incompatible(r); |
139 | ||
140 | if (reason != FSMONITOR_REASON_OK) { | |
141 | fsm_settings__set_incompatible(r, reason); | |
142 | return; | |
143 | } | |
144 | ||
145 | /* | |
146 | * Caller requested hook explicitly, so avoid (possibly | |
147 | * recursive) config lookup. | |
148 | */ | |
1e0ea5c4 JH |
149 | if (!r) |
150 | r = the_repository; | |
62a62a28 JH |
151 | if (!r->settings.fsmonitor) |
152 | r->settings.fsmonitor = alloc_settings(); | |
1e0ea5c4 JH |
153 | |
154 | r->settings.fsmonitor->mode = FSMONITOR_MODE_HOOK; | |
62a62a28 | 155 | r->settings.fsmonitor->reason = reason; |
1e0ea5c4 JH |
156 | FREE_AND_NULL(r->settings.fsmonitor->hook_path); |
157 | r->settings.fsmonitor->hook_path = strdup(path); | |
158 | } | |
159 | ||
160 | void fsm_settings__set_disabled(struct repository *r) | |
161 | { | |
162 | if (!r) | |
163 | r = the_repository; | |
62a62a28 JH |
164 | if (!r->settings.fsmonitor) |
165 | r->settings.fsmonitor = alloc_settings(); | |
1e0ea5c4 JH |
166 | |
167 | r->settings.fsmonitor->mode = FSMONITOR_MODE_DISABLED; | |
62a62a28 JH |
168 | r->settings.fsmonitor->reason = FSMONITOR_REASON_OK; |
169 | FREE_AND_NULL(r->settings.fsmonitor->hook_path); | |
170 | } | |
171 | ||
172 | void fsm_settings__set_incompatible(struct repository *r, | |
173 | enum fsmonitor_reason reason) | |
174 | { | |
175 | if (!r) | |
176 | r = the_repository; | |
177 | if (!r->settings.fsmonitor) | |
178 | r->settings.fsmonitor = alloc_settings(); | |
179 | ||
180 | r->settings.fsmonitor->mode = FSMONITOR_MODE_INCOMPATIBLE; | |
181 | r->settings.fsmonitor->reason = reason; | |
1e0ea5c4 JH |
182 | FREE_AND_NULL(r->settings.fsmonitor->hook_path); |
183 | } | |
62a62a28 JH |
184 | |
185 | enum fsmonitor_reason fsm_settings__get_reason(struct repository *r) | |
186 | { | |
187 | if (!r) | |
188 | r = the_repository; | |
189 | if (!r->settings.fsmonitor) | |
190 | lookup_fsmonitor_settings(r); | |
191 | ||
192 | return r->settings.fsmonitor->reason; | |
193 | } | |
194 | ||
195 | char *fsm_settings__get_incompatible_msg(const struct repository *r, | |
196 | enum fsmonitor_reason reason) | |
197 | { | |
198 | struct strbuf msg = STRBUF_INIT; | |
199 | ||
200 | switch (reason) { | |
201 | case FSMONITOR_REASON_UNTESTED: | |
202 | case FSMONITOR_REASON_OK: | |
203 | goto done; | |
204 | ||
5a09991e JS |
205 | case FSMONITOR_REASON_BARE: { |
206 | char *cwd = xgetcwd(); | |
207 | ||
62a62a28 JH |
208 | strbuf_addf(&msg, |
209 | _("bare repository '%s' is incompatible with fsmonitor"), | |
5a09991e JS |
210 | cwd); |
211 | free(cwd); | |
62a62a28 | 212 | goto done; |
5a09991e | 213 | } |
5c58fbd2 | 214 | |
1e7be10d JH |
215 | case FSMONITOR_REASON_ERROR: |
216 | strbuf_addf(&msg, | |
217 | _("repository '%s' is incompatible with fsmonitor due to errors"), | |
218 | r->worktree); | |
219 | goto done; | |
220 | ||
221 | case FSMONITOR_REASON_REMOTE: | |
222 | strbuf_addf(&msg, | |
223 | _("remote repository '%s' is incompatible with fsmonitor"), | |
224 | r->worktree); | |
225 | goto done; | |
226 | ||
5c58fbd2 JH |
227 | case FSMONITOR_REASON_VFS4GIT: |
228 | strbuf_addf(&msg, | |
229 | _("virtual repository '%s' is incompatible with fsmonitor"), | |
230 | r->worktree); | |
231 | goto done; | |
ddc5dacf JH |
232 | |
233 | case FSMONITOR_REASON_NOSOCKETS: | |
234 | strbuf_addf(&msg, | |
235 | _("repository '%s' is incompatible with fsmonitor due to lack of Unix sockets"), | |
236 | r->worktree); | |
237 | goto done; | |
62a62a28 JH |
238 | } |
239 | ||
240 | BUG("Unhandled case in fsm_settings__get_incompatible_msg: '%d'", | |
241 | reason); | |
242 | ||
243 | done: | |
244 | return strbuf_detach(&msg, NULL); | |
245 | } |