8
9
#define INDEX_EXTENSION_VERSION1 (1)
10
#define INDEX_EXTENSION_VERSION2 (2)
11
-#define HOOK_INTERFACE_VERSION (1)
11
+#define HOOK_INTERFACE_VERSION1 (1)
12
+#define HOOK_INTERFACE_VERSION2 (2)
13
14
struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
15
26
ce->ce_flags &= ~CE_FSMONITOR_VALID;
27
}
28
29
+static int fsmonitor_hook_version(void)
30
+{
31
+ int hook_version;
32
+
33
+ if (git_config_get_int("core.fsmonitorhookversion", &hook_version))
34
+ return -1;
35
+
36
+ if (hook_version == HOOK_INTERFACE_VERSION1 ||
37
+ hook_version == HOOK_INTERFACE_VERSION2)
38
+ return hook_version;
39
+
40
+ warning("Invalid hook version '%i' in core.fsmonitorhookversion. "
41
+ "Must be 1 or 2.", hook_version);
42
+ return -1;
43
+}
44
+
45
int read_fsmonitor_extension(struct index_state *istate, const void *data,
46
unsigned long sz)
47
{
175
void refresh_fsmonitor(struct index_state *istate)
176
{
177
struct strbuf query_result = STRBUF_INIT;
161
- int query_success = 0;
162
- size_t bol; /* beginning of line */
178
+ int query_success = 0, hook_version = -1;
179
+ size_t bol = 0; /* beginning of line */
180
uint64_t last_update;
181
struct strbuf last_update_token = STRBUF_INIT;
182
char *buf;
184
185
if (!core_fsmonitor || istate->fsmonitor_has_run_once)
186
return;
187
+
188
+ hook_version = fsmonitor_hook_version();
189
+
190
istate->fsmonitor_has_run_once = 1;
191
192
trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
195
* should be inclusive to ensure we don't miss potential changes.
196
*/
197
last_update = getnanotime();
178
- strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
198
+ if (hook_version == HOOK_INTERFACE_VERSION1)
199
+ strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
200
201
/*
181
- * If we have a last update time, call query_fsmonitor for the set of
182
- * changes since that time, else assume everything is possibly dirty
202
+ * If we have a last update token, call query_fsmonitor for the set of
203
+ * changes since that token, else assume everything is possibly dirty
204
* and check it all.
205
*/
206
if (istate->fsmonitor_last_update) {
186
- query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION,
187
- istate->fsmonitor_last_update, &query_result);
207
+ if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {
208
+ query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION2,
209
+ istate->fsmonitor_last_update, &query_result);
210
+
211
+ if (query_success) {
212
+ if (hook_version < 0)
213
+ hook_version = HOOK_INTERFACE_VERSION2;
214
+
215
+ /*
216
+ * First entry will be the last update token
217
+ * Need to use a char * variable because static
218
+ * analysis was suggesting to use strbuf_addbuf
219
+ * but we don't want to copy the entire strbuf
220
+ * only the the chars up to the first NUL
221
+ */
222
+ buf = query_result.buf;
223
+ strbuf_addstr(&last_update_token, buf);
224
+ if (!last_update_token.len) {
225
+ warning("Empty last update token.");
226
+ query_success = 0;
227
+ } else {
228
+ bol = last_update_token.len + 1;
229
+ }
230
+ } else if (hook_version < 0) {
231
+ hook_version = HOOK_INTERFACE_VERSION1;
232
+ if (!last_update_token.len)
233
+ strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
234
+ }
235
+ }
236
+
237
+ if (hook_version == HOOK_INTERFACE_VERSION1) {
238
+ query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION1,
239
+ istate->fsmonitor_last_update, &query_result);
240
+ }
241
+
242
trace_performance_since(last_update, "fsmonitor process '%s'", core_fsmonitor);
243
trace_printf_key(&trace_fsmonitor, "fsmonitor process '%s' returned %s",
244
core_fsmonitor, query_success ? "success" : "failure");
245
}
246
247
/* a fsmonitor process can return '/' to indicate all entries are invalid */
194
- if (query_success && query_result.buf[0] != '/') {
248
+ if (query_success && query_result.buf[bol] != '/') {
249
/* Mark all entries returned by the monitor as dirty */
250
buf = query_result.buf;
197
- bol = 0;
198
- for (i = 0; i < query_result.len; i++) {
251
+ for (i = bol; i < query_result.len; i++) {
252
if (buf[i] != '\0')
253
continue;
254
fsmonitor_refresh_callback(istate, buf + bol);