Coverage Report

Created: 2024-09-16 06:11

/src/git/fsmonitor.c
Line
Count
Source (jump to first uncovered line)
1
#define USE_THE_REPOSITORY_VARIABLE
2
3
#include "git-compat-util.h"
4
#include "config.h"
5
#include "dir.h"
6
#include "environment.h"
7
#include "ewah/ewok.h"
8
#include "fsmonitor.h"
9
#include "fsmonitor-ipc.h"
10
#include "name-hash.h"
11
#include "run-command.h"
12
#include "strbuf.h"
13
#include "trace2.h"
14
15
0
#define INDEX_EXTENSION_VERSION1  (1)
16
0
#define INDEX_EXTENSION_VERSION2  (2)
17
0
#define HOOK_INTERFACE_VERSION1   (1)
18
0
#define HOOK_INTERFACE_VERSION2   (2)
19
20
struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
21
22
static void assert_index_minimum(struct index_state *istate, size_t pos)
23
0
{
24
0
  if (pos > istate->cache_nr)
25
0
    BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
26
0
        (uintmax_t)pos, istate->cache_nr);
27
0
}
28
29
static void fsmonitor_ewah_callback(size_t pos, void *is)
30
0
{
31
0
  struct index_state *istate = (struct index_state *)is;
32
0
  struct cache_entry *ce;
33
34
0
  assert_index_minimum(istate, pos + 1);
35
36
0
  ce = istate->cache[pos];
37
0
  ce->ce_flags &= ~CE_FSMONITOR_VALID;
38
0
}
39
40
static int fsmonitor_hook_version(void)
41
0
{
42
0
  int hook_version;
43
44
0
  if (git_config_get_int("core.fsmonitorhookversion", &hook_version))
45
0
    return -1;
46
47
0
  if (hook_version == HOOK_INTERFACE_VERSION1 ||
48
0
      hook_version == HOOK_INTERFACE_VERSION2)
49
0
    return hook_version;
50
51
0
  warning("Invalid hook version '%i' in core.fsmonitorhookversion. "
52
0
    "Must be 1 or 2.", hook_version);
53
0
  return -1;
54
0
}
55
56
int read_fsmonitor_extension(struct index_state *istate, const void *data,
57
  unsigned long sz)
58
0
{
59
0
  const char *index = data;
60
0
  uint32_t hdr_version;
61
0
  uint32_t ewah_size;
62
0
  struct ewah_bitmap *fsmonitor_dirty;
63
0
  int ret;
64
0
  uint64_t timestamp;
65
0
  struct strbuf last_update = STRBUF_INIT;
66
67
0
  if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))
68
0
    return error("corrupt fsmonitor extension (too short)");
69
70
0
  hdr_version = get_be32(index);
71
0
  index += sizeof(uint32_t);
72
0
  if (hdr_version == INDEX_EXTENSION_VERSION1) {
73
0
    timestamp = get_be64(index);
74
0
    strbuf_addf(&last_update, "%"PRIu64"", timestamp);
75
0
    index += sizeof(uint64_t);
76
0
  } else if (hdr_version == INDEX_EXTENSION_VERSION2) {
77
0
    strbuf_addstr(&last_update, index);
78
0
    index += last_update.len + 1;
79
0
  } else {
80
0
    return error("bad fsmonitor version %d", hdr_version);
81
0
  }
82
83
0
  istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
84
85
0
  ewah_size = get_be32(index);
86
0
  index += sizeof(uint32_t);
87
88
0
  fsmonitor_dirty = ewah_new();
89
0
  ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);
90
0
  if (ret != ewah_size) {
91
0
    ewah_free(fsmonitor_dirty);
92
0
    return error("failed to parse ewah bitmap reading fsmonitor index extension");
93
0
  }
94
0
  istate->fsmonitor_dirty = fsmonitor_dirty;
95
96
0
  if (!istate->split_index)
97
0
    assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
98
99
0
  trace2_data_string("index", NULL, "extension/fsmn/read/token",
100
0
         istate->fsmonitor_last_update);
101
0
  trace_printf_key(&trace_fsmonitor,
102
0
       "read fsmonitor extension successful '%s'",
103
0
       istate->fsmonitor_last_update);
104
0
  return 0;
105
0
}
106
107
void fill_fsmonitor_bitmap(struct index_state *istate)
108
0
{
109
0
  unsigned int i, skipped = 0;
110
0
  istate->fsmonitor_dirty = ewah_new();
111
0
  for (i = 0; i < istate->cache_nr; i++) {
112
0
    if (istate->cache[i]->ce_flags & CE_REMOVE)
113
0
      skipped++;
114
0
    else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
115
0
      ewah_set(istate->fsmonitor_dirty, i - skipped);
116
0
  }
117
0
}
118
119
void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
120
0
{
121
0
  uint32_t hdr_version;
122
0
  uint32_t ewah_start;
123
0
  uint32_t ewah_size = 0;
124
0
  int fixup = 0;
125
126
0
  if (!istate->split_index)
127
0
    assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
128
129
0
  put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);
130
0
  strbuf_add(sb, &hdr_version, sizeof(uint32_t));
131
132
0
  strbuf_addstr(sb, istate->fsmonitor_last_update);
133
0
  strbuf_addch(sb, 0); /* Want to keep a NUL */
134
135
0
  fixup = sb->len;
136
0
  strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
137
138
0
  ewah_start = sb->len;
139
0
  ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
140
0
  ewah_free(istate->fsmonitor_dirty);
141
0
  istate->fsmonitor_dirty = NULL;
142
143
  /* fix up size field */
144
0
  put_be32(&ewah_size, sb->len - ewah_start);
145
0
  memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));
146
147
0
  trace2_data_string("index", NULL, "extension/fsmn/write/token",
148
0
         istate->fsmonitor_last_update);
149
0
  trace_printf_key(&trace_fsmonitor,
150
0
       "write fsmonitor extension successful '%s'",
151
0
       istate->fsmonitor_last_update);
152
0
}
153
154
/*
155
 * Call the query-fsmonitor hook passing the last update token of the saved results.
156
 */
157
static int query_fsmonitor_hook(struct repository *r,
158
        int version,
159
        const char *last_update,
160
        struct strbuf *query_result)
161
0
{
162
0
  struct child_process cp = CHILD_PROCESS_INIT;
163
0
  int result;
164
165
0
  if (fsm_settings__get_mode(r) != FSMONITOR_MODE_HOOK)
166
0
    return -1;
167
168
0
  strvec_push(&cp.args, fsm_settings__get_hook_path(r));
169
0
  strvec_pushf(&cp.args, "%d", version);
170
0
  strvec_pushf(&cp.args, "%s", last_update);
171
0
  cp.use_shell = 1;
172
0
  cp.dir = get_git_work_tree();
173
174
0
  trace2_region_enter("fsm_hook", "query", NULL);
175
176
0
  result = capture_command(&cp, query_result, 1024);
177
178
0
  if (result)
179
0
    trace2_data_intmax("fsm_hook", NULL, "query/failed", result);
180
0
  else
181
0
    trace2_data_intmax("fsm_hook", NULL, "query/response-length",
182
0
           query_result->len);
183
184
0
  trace2_region_leave("fsm_hook", "query", NULL);
185
186
0
  return result;
187
0
}
188
189
/*
190
 * Invalidate the FSM bit on this CE.  This is like mark_fsmonitor_invalid()
191
 * but we've already handled the untracked-cache, so let's not repeat that
192
 * work.  This also lets us have a different trace message so that we can
193
 * see everything that was done as part of the refresh-callback.
194
 */
195
static void invalidate_ce_fsm(struct cache_entry *ce)
196
0
{
197
0
  if (ce->ce_flags & CE_FSMONITOR_VALID) {
198
0
    trace_printf_key(&trace_fsmonitor,
199
0
         "fsmonitor_refresh_callback INV: '%s'",
200
0
         ce->name);
201
0
    ce->ce_flags &= ~CE_FSMONITOR_VALID;
202
0
  }
203
0
}
204
205
static size_t handle_path_with_trailing_slash(
206
  struct index_state *istate, const char *name, int pos);
207
208
/*
209
 * Use the name-hash to do a case-insensitive cache-entry lookup with
210
 * the pathname and invalidate the cache-entry.
211
 *
212
 * Returns the number of cache-entries that we invalidated.
213
 */
214
static size_t handle_using_name_hash_icase(
215
  struct index_state *istate, const char *name)
216
0
{
217
0
  struct cache_entry *ce = NULL;
218
219
0
  ce = index_file_exists(istate, name, strlen(name), 1);
220
0
  if (!ce)
221
0
    return 0;
222
223
  /*
224
   * A case-insensitive search in the name-hash using the
225
   * observed pathname found a cache-entry, so the observed path
226
   * is case-incorrect.  Invalidate the cache-entry and use the
227
   * correct spelling from the cache-entry to invalidate the
228
   * untracked-cache.  Since we now have sparse-directories in
229
   * the index, the observed pathname may represent a regular
230
   * file or a sparse-index directory.
231
   *
232
   * Note that we should not have seen FSEvents for a
233
   * sparse-index directory, but we handle it just in case.
234
   *
235
   * Either way, we know that there are not any cache-entries for
236
   * children inside the cone of the directory, so we don't need to
237
   * do the usual scan.
238
   */
239
0
  trace_printf_key(&trace_fsmonitor,
240
0
       "fsmonitor_refresh_callback MAP: '%s' '%s'",
241
0
       name, ce->name);
242
243
  /*
244
   * NEEDSWORK: We used the name-hash to find the correct
245
   * case-spelling of the pathname in the cache-entry[], so
246
   * technically this is a tracked file or a sparse-directory.
247
   * It should not have any entries in the untracked-cache, so
248
   * we should not need to use the case-corrected spelling to
249
   * invalidate the the untracked-cache.  So we may not need to
250
   * do this.  For now, I'm going to be conservative and always
251
   * do it; we can revisit this later.
252
   */
253
0
  untracked_cache_invalidate_trimmed_path(istate, ce->name, 0);
254
255
0
  invalidate_ce_fsm(ce);
256
0
  return 1;
257
0
}
258
259
/*
260
 * Use the dir-name-hash to find the correct-case spelling of the
261
 * directory.  Use the canonical spelling to invalidate all of the
262
 * cache-entries within the matching cone.
263
 *
264
 * Returns the number of cache-entries that we invalidated.
265
 */
266
static size_t handle_using_dir_name_hash_icase(
267
  struct index_state *istate, const char *name)
268
0
{
269
0
  struct strbuf canonical_path = STRBUF_INIT;
270
0
  int pos;
271
0
  size_t len = strlen(name);
272
0
  size_t nr_in_cone;
273
274
0
  if (name[len - 1] == '/')
275
0
    len--;
276
277
0
  if (!index_dir_find(istate, name, len, &canonical_path))
278
0
    return 0; /* name is untracked */
279
280
0
  if (!memcmp(name, canonical_path.buf, canonical_path.len)) {
281
0
    strbuf_release(&canonical_path);
282
    /*
283
     * NEEDSWORK: Our caller already tried an exact match
284
     * and failed to find one.  They called us to do an
285
     * ICASE match, so we should never get an exact match,
286
     * so we could promote this to a BUG() here if we
287
     * wanted to.  It doesn't hurt anything to just return
288
     * 0 and go on because we should never get here.  Or we
289
     * could just get rid of the memcmp() and this "if"
290
     * clause completely.
291
     */
292
0
    BUG("handle_using_dir_name_hash_icase(%s) did not exact match",
293
0
        name);
294
0
  }
295
296
0
  trace_printf_key(&trace_fsmonitor,
297
0
       "fsmonitor_refresh_callback MAP: '%s' '%s'",
298
0
       name, canonical_path.buf);
299
300
  /*
301
   * The dir-name-hash only tells us the corrected spelling of
302
   * the prefix.  We have to use this canonical path to do a
303
   * lookup in the cache-entry array so that we repeat the
304
   * original search using the case-corrected spelling.
305
   */
306
0
  strbuf_addch(&canonical_path, '/');
307
0
  pos = index_name_pos(istate, canonical_path.buf,
308
0
           canonical_path.len);
309
0
  nr_in_cone = handle_path_with_trailing_slash(
310
0
    istate, canonical_path.buf, pos);
311
0
  strbuf_release(&canonical_path);
312
0
  return nr_in_cone;
313
0
}
314
315
/*
316
 * The daemon sent an observed pathname without a trailing slash.
317
 * (This is the normal case.)  We do not know if it is a tracked or
318
 * untracked file, a sparse-directory, or a populated directory (on a
319
 * platform such as Windows where FSEvents are not qualified).
320
 *
321
 * The pathname contains the observed case reported by the FS. We
322
 * do not know it is case-correct or -incorrect.
323
 *
324
 * Assume it is case-correct and try an exact match.
325
 *
326
 * Return the number of cache-entries that we invalidated.
327
 */
328
static size_t handle_path_without_trailing_slash(
329
  struct index_state *istate, const char *name, int pos)
330
0
{
331
  /*
332
   * Mark the untracked cache dirty for this path (regardless of
333
   * whether or not we find an exact match for it in the index).
334
   * Since the path is unqualified (no trailing slash hint in the
335
   * FSEvent), it may refer to a file or directory. So we should
336
   * not assume one or the other and should always let the untracked
337
   * cache decide what needs to invalidated.
338
   */
339
0
  untracked_cache_invalidate_trimmed_path(istate, name, 0);
340
341
0
  if (pos >= 0) {
342
    /*
343
     * An exact match on a tracked file. We assume that we
344
     * do not need to scan forward for a sparse-directory
345
     * cache-entry with the same pathname, nor for a cone
346
     * at that directory. (That is, assume no D/F conflicts.)
347
     */
348
0
    invalidate_ce_fsm(istate->cache[pos]);
349
0
    return 1;
350
0
  } else {
351
0
    size_t nr_in_cone;
352
0
    struct strbuf work_path = STRBUF_INIT;
353
354
    /*
355
     * The negative "pos" gives us the suggested insertion
356
     * point for the pathname (without the trailing slash).
357
     * We need to see if there is a directory with that
358
     * prefix, but there can be lots of pathnames between
359
     * "foo" and "foo/" like "foo-" or "foo-bar", so we
360
     * don't want to do our own scan.
361
     */
362
0
    strbuf_add(&work_path, name, strlen(name));
363
0
    strbuf_addch(&work_path, '/');
364
0
    pos = index_name_pos(istate, work_path.buf, work_path.len);
365
0
    nr_in_cone = handle_path_with_trailing_slash(
366
0
      istate, work_path.buf, pos);
367
0
    strbuf_release(&work_path);
368
0
    return nr_in_cone;
369
0
  }
370
0
}
371
372
/*
373
 * The daemon can decorate directory events, such as a move or rename,
374
 * by adding a trailing slash to the observed name.  Use this to
375
 * explicitly invalidate the entire cone under that directory.
376
 *
377
 * The daemon can only reliably do that if the OS FSEvent contains
378
 * sufficient information in the event.
379
 *
380
 * macOS FSEvents have enough information.
381
 *
382
 * Other platforms may or may not be able to do it (and it might
383
 * depend on the type of event (for example, a daemon could lstat() an
384
 * observed pathname after a rename, but not after a delete)).
385
 *
386
 * If we find an exact match in the index for a path with a trailing
387
 * slash, it means that we matched a sparse-index directory in a
388
 * cone-mode sparse-checkout (since that's the only time we have
389
 * directories in the index).  We should never see this in practice
390
 * (because sparse directories should not be present and therefore
391
 * not generating FS events).  Either way, we can treat them in the
392
 * same way and just invalidate the cache-entry and the untracked
393
 * cache (and in this case, the forward cache-entry scan won't find
394
 * anything and it doesn't hurt to let it run).
395
 *
396
 * Return the number of cache-entries that we invalidated.  We will
397
 * use this later to determine if we need to attempt a second
398
 * case-insensitive search on case-insensitive file systems.  That is,
399
 * if the search using the observed-case in the FSEvent yields any
400
 * results, we assume the prefix is case-correct.  If there are no
401
 * matches, we still don't know if the observed path is simply
402
 * untracked or case-incorrect.
403
 */
404
static size_t handle_path_with_trailing_slash(
405
  struct index_state *istate, const char *name, int pos)
406
0
{
407
0
  int i;
408
0
  size_t nr_in_cone = 0;
409
410
  /*
411
   * Mark the untracked cache dirty for this directory path
412
   * (regardless of whether or not we find an exact match for it
413
   * in the index or find it to be proper prefix of one or more
414
   * files in the index), since the FSEvent is hinting that
415
   * there may be changes on or within the directory.
416
   */
417
0
  untracked_cache_invalidate_trimmed_path(istate, name, 0);
418
419
0
  if (pos < 0)
420
0
    pos = -pos - 1;
421
422
  /* Mark all entries for the folder invalid */
423
0
  for (i = pos; i < istate->cache_nr; i++) {
424
0
    if (!starts_with(istate->cache[i]->name, name))
425
0
      break;
426
0
    invalidate_ce_fsm(istate->cache[i]);
427
0
    nr_in_cone++;
428
0
  }
429
430
0
  return nr_in_cone;
431
0
}
432
433
static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
434
0
{
435
0
  int len = strlen(name);
436
0
  int pos = index_name_pos(istate, name, len);
437
0
  size_t nr_in_cone;
438
439
0
  trace_printf_key(&trace_fsmonitor,
440
0
       "fsmonitor_refresh_callback '%s' (pos %d)",
441
0
       name, pos);
442
443
0
  if (name[len - 1] == '/')
444
0
    nr_in_cone = handle_path_with_trailing_slash(istate, name, pos);
445
0
  else
446
0
    nr_in_cone = handle_path_without_trailing_slash(istate, name, pos);
447
448
  /*
449
   * If we did not find an exact match for this pathname or any
450
   * cache-entries with this directory prefix and we're on a
451
   * case-insensitive file system, try again using the name-hash
452
   * and dir-name-hash.
453
   */
454
0
  if (!nr_in_cone && ignore_case) {
455
0
    nr_in_cone = handle_using_name_hash_icase(istate, name);
456
0
    if (!nr_in_cone)
457
0
      nr_in_cone = handle_using_dir_name_hash_icase(
458
0
        istate, name);
459
0
  }
460
461
0
  if (nr_in_cone)
462
0
    trace_printf_key(&trace_fsmonitor,
463
0
         "fsmonitor_refresh_callback CNT: %d",
464
0
         (int)nr_in_cone);
465
0
}
466
467
/*
468
 * The number of pathnames that we need to receive from FSMonitor
469
 * before we force the index to be updated.
470
 *
471
 * Note that any pathname within the set of received paths MAY cause
472
 * cache-entry or istate flag bits to be updated and thus cause the
473
 * index to be updated on disk.
474
 *
475
 * However, the response may contain many paths (such as ignored
476
 * paths) that will not update any flag bits.  And thus not force the
477
 * index to be updated.  (This is fine and normal.)  It also means
478
 * that the token will not be updated in the FSMonitor index
479
 * extension.  So the next Git command will find the same token in the
480
 * index, make the same token-relative request, and receive the same
481
 * response (plus any newly changed paths).  If this response is large
482
 * (and continues to grow), performance could be impacted.
483
 *
484
 * For example, if the user runs a build and it writes 100K object
485
 * files but doesn't modify any source files, the index would not need
486
 * to be updated.  The FSMonitor response (after the build and
487
 * relative to a pre-build token) might be 5MB.  Each subsequent Git
488
 * command will receive that same 100K/5MB response until something
489
 * causes the index to be updated.  And `refresh_fsmonitor()` will
490
 * have to iterate over those 100K paths each time.
491
 *
492
 * Performance could be improved if we optionally force update the
493
 * index after a very large response and get an updated token into
494
 * the FSMonitor index extension.  This should allow subsequent
495
 * commands to get smaller and more current responses.
496
 *
497
 * The value chosen here does not need to be precise.  The index
498
 * will be updated automatically the first time the user touches
499
 * a tracked file and causes a command like `git status` to
500
 * update an mtime to be updated and/or set a flag bit.
501
 */
502
static int fsmonitor_force_update_threshold = 100;
503
504
void refresh_fsmonitor(struct index_state *istate)
505
0
{
506
0
  static int warn_once = 0;
507
0
  struct strbuf query_result = STRBUF_INIT;
508
0
  int query_success = 0, hook_version = -1;
509
0
  size_t bol = 0; /* beginning of line */
510
0
  uint64_t last_update;
511
0
  struct strbuf last_update_token = STRBUF_INIT;
512
0
  char *buf;
513
0
  unsigned int i;
514
0
  int is_trivial = 0;
515
0
  struct repository *r = istate->repo;
516
0
  enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
517
0
  enum fsmonitor_reason reason = fsm_settings__get_reason(r);
518
519
0
  if (!warn_once && reason > FSMONITOR_REASON_OK) {
520
0
    char *msg = fsm_settings__get_incompatible_msg(r, reason);
521
0
    warn_once = 1;
522
0
    warning("%s", msg);
523
0
    free(msg);
524
0
  }
525
526
0
  if (fsm_mode <= FSMONITOR_MODE_DISABLED ||
527
0
      istate->fsmonitor_has_run_once)
528
0
    return;
529
530
0
  istate->fsmonitor_has_run_once = 1;
531
532
0
  trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
533
534
0
  if (fsm_mode == FSMONITOR_MODE_IPC) {
535
0
    query_success = !fsmonitor_ipc__send_query(
536
0
      istate->fsmonitor_last_update ?
537
0
      istate->fsmonitor_last_update : "builtin:fake",
538
0
      &query_result);
539
0
    if (query_success) {
540
      /*
541
       * The response contains a series of nul terminated
542
       * strings.  The first is the new token.
543
       *
544
       * Use `char *buf` as an interlude to trick the CI
545
       * static analysis to let us use `strbuf_addstr()`
546
       * here (and only copy the token) rather than
547
       * `strbuf_addbuf()`.
548
       */
549
0
      buf = query_result.buf;
550
0
      strbuf_addstr(&last_update_token, buf);
551
0
      bol = last_update_token.len + 1;
552
0
      is_trivial = query_result.buf[bol] == '/';
553
0
      if (is_trivial)
554
0
        trace2_data_intmax("fsm_client", NULL,
555
0
               "query/trivial-response", 1);
556
0
    } else {
557
      /*
558
       * The builtin daemon is not available on this
559
       * platform -OR- we failed to get a response.
560
       *
561
       * Generate a fake token (rather than a V1
562
       * timestamp) for the index extension.  (If
563
       * they switch back to the hook API, we don't
564
       * want ambiguous state.)
565
       */
566
0
      strbuf_addstr(&last_update_token, "builtin:fake");
567
0
    }
568
569
0
    goto apply_results;
570
0
  }
571
572
0
  assert(fsm_mode == FSMONITOR_MODE_HOOK);
573
574
0
  hook_version = fsmonitor_hook_version();
575
576
  /*
577
   * This could be racy so save the date/time now and query_fsmonitor_hook
578
   * should be inclusive to ensure we don't miss potential changes.
579
   */
580
0
  last_update = getnanotime();
581
0
  if (hook_version == HOOK_INTERFACE_VERSION1)
582
0
    strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
583
584
  /*
585
   * If we have a last update token, call query_fsmonitor_hook for the set of
586
   * changes since that token, else assume everything is possibly dirty
587
   * and check it all.
588
   */
589
0
  if (istate->fsmonitor_last_update) {
590
0
    if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {
591
0
      query_success = !query_fsmonitor_hook(
592
0
        r, HOOK_INTERFACE_VERSION2,
593
0
        istate->fsmonitor_last_update, &query_result);
594
595
0
      if (query_success) {
596
0
        if (hook_version < 0)
597
0
          hook_version = HOOK_INTERFACE_VERSION2;
598
599
        /*
600
         * First entry will be the last update token
601
         * Need to use a char * variable because static
602
         * analysis was suggesting to use strbuf_addbuf
603
         * but we don't want to copy the entire strbuf
604
         * only the chars up to the first NUL
605
         */
606
0
        buf = query_result.buf;
607
0
        strbuf_addstr(&last_update_token, buf);
608
0
        if (!last_update_token.len) {
609
0
          warning("Empty last update token.");
610
0
          query_success = 0;
611
0
        } else {
612
0
          bol = last_update_token.len + 1;
613
0
          is_trivial = query_result.buf[bol] == '/';
614
0
        }
615
0
      } else if (hook_version < 0) {
616
0
        hook_version = HOOK_INTERFACE_VERSION1;
617
0
        if (!last_update_token.len)
618
0
          strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
619
0
      }
620
0
    }
621
622
0
    if (hook_version == HOOK_INTERFACE_VERSION1) {
623
0
      query_success = !query_fsmonitor_hook(
624
0
        r, HOOK_INTERFACE_VERSION1,
625
0
        istate->fsmonitor_last_update, &query_result);
626
0
      if (query_success)
627
0
        is_trivial = query_result.buf[0] == '/';
628
0
    }
629
630
0
    if (is_trivial)
631
0
      trace2_data_intmax("fsm_hook", NULL,
632
0
             "query/trivial-response", 1);
633
634
0
    trace_performance_since(last_update, "fsmonitor process '%s'",
635
0
          fsm_settings__get_hook_path(r));
636
0
    trace_printf_key(&trace_fsmonitor,
637
0
         "fsmonitor process '%s' returned %s",
638
0
         fsm_settings__get_hook_path(r),
639
0
         query_success ? "success" : "failure");
640
0
  }
641
642
0
apply_results:
643
  /*
644
   * The response from FSMonitor (excluding the header token) is
645
   * either:
646
   *
647
   * [a] a (possibly empty) list of NUL delimited relative
648
   *     pathnames of changed paths.  This list can contain
649
   *     files and directories.  Directories have a trailing
650
   *     slash.
651
   *
652
   * [b] a single '/' to indicate the provider had no
653
   *     information and that we should consider everything
654
   *     invalid.  We call this a trivial response.
655
   */
656
0
  trace2_region_enter("fsmonitor", "apply_results", istate->repo);
657
658
0
  if (query_success && !is_trivial) {
659
    /*
660
     * Mark all pathnames returned by the monitor as dirty.
661
     *
662
     * This updates both the cache-entries and the untracked-cache.
663
     */
664
0
    int count = 0;
665
666
0
    buf = query_result.buf;
667
0
    for (i = bol; i < query_result.len; i++) {
668
0
      if (buf[i] != '\0')
669
0
        continue;
670
0
      fsmonitor_refresh_callback(istate, buf + bol);
671
0
      bol = i + 1;
672
0
      count++;
673
0
    }
674
0
    if (bol < query_result.len) {
675
0
      fsmonitor_refresh_callback(istate, buf + bol);
676
0
      count++;
677
0
    }
678
679
    /* Now mark the untracked cache for fsmonitor usage */
680
0
    if (istate->untracked)
681
0
      istate->untracked->use_fsmonitor = 1;
682
683
0
    if (count > fsmonitor_force_update_threshold)
684
0
      istate->cache_changed |= FSMONITOR_CHANGED;
685
686
0
    trace2_data_intmax("fsmonitor", istate->repo, "apply_count",
687
0
           count);
688
689
0
  } else {
690
    /*
691
     * We failed to get a response or received a trivial response,
692
     * so invalidate everything.
693
     *
694
     * We only want to run the post index changed hook if
695
     * we've actually changed entries, so keep track if we
696
     * actually changed entries or not.
697
     */
698
0
    int is_cache_changed = 0;
699
700
0
    for (i = 0; i < istate->cache_nr; i++) {
701
0
      if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) {
702
0
        is_cache_changed = 1;
703
0
        istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
704
0
      }
705
0
    }
706
707
    /*
708
     * If we're going to check every file, ensure we save
709
     * the results.
710
     */
711
0
    if (is_cache_changed)
712
0
      istate->cache_changed |= FSMONITOR_CHANGED;
713
714
0
    if (istate->untracked)
715
0
      istate->untracked->use_fsmonitor = 0;
716
0
  }
717
0
  trace2_region_leave("fsmonitor", "apply_results", istate->repo);
718
719
0
  strbuf_release(&query_result);
720
721
  /* Now that we've updated istate, save the last_update_token */
722
0
  FREE_AND_NULL(istate->fsmonitor_last_update);
723
0
  istate->fsmonitor_last_update = strbuf_detach(&last_update_token, NULL);
724
0
}
725
726
/*
727
 * The caller wants to turn on FSMonitor.  And when the caller writes
728
 * the index to disk, a FSMonitor extension should be included.  This
729
 * requires that `istate->fsmonitor_last_update` not be NULL.  But we
730
 * have not actually talked to a FSMonitor process yet, so we don't
731
 * have an initial value for this field.
732
 *
733
 * For a protocol V1 FSMonitor process, this field is a formatted
734
 * "nanoseconds since epoch" field.  However, for a protocol V2
735
 * FSMonitor process, this field is an opaque token.
736
 *
737
 * Historically, `add_fsmonitor()` has initialized this field to the
738
 * current time for protocol V1 processes.  There are lots of race
739
 * conditions here, but that code has shipped...
740
 *
741
 * The only true solution is to use a V2 FSMonitor and get a current
742
 * or default token value (that it understands), but we cannot do that
743
 * until we have actually talked to an instance of the FSMonitor process
744
 * (but the protocol requires that we send a token first...).
745
 *
746
 * For simplicity, just initialize like we have a V1 process and require
747
 * that V2 processes adapt.
748
 */
749
static void initialize_fsmonitor_last_update(struct index_state *istate)
750
0
{
751
0
  struct strbuf last_update = STRBUF_INIT;
752
753
0
  strbuf_addf(&last_update, "%"PRIu64"", getnanotime());
754
0
  istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
755
0
}
756
757
void add_fsmonitor(struct index_state *istate)
758
0
{
759
0
  unsigned int i;
760
761
0
  if (!istate->fsmonitor_last_update) {
762
0
    trace_printf_key(&trace_fsmonitor, "add fsmonitor");
763
0
    istate->cache_changed |= FSMONITOR_CHANGED;
764
0
    initialize_fsmonitor_last_update(istate);
765
766
    /* reset the fsmonitor state */
767
0
    for (i = 0; i < istate->cache_nr; i++)
768
0
      istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
769
770
    /* reset the untracked cache */
771
0
    if (istate->untracked) {
772
0
      add_untracked_cache(istate);
773
0
      istate->untracked->use_fsmonitor = 1;
774
0
    }
775
776
    /* Update the fsmonitor state */
777
0
    refresh_fsmonitor(istate);
778
0
  }
779
0
}
780
781
void remove_fsmonitor(struct index_state *istate)
782
0
{
783
0
  if (istate->fsmonitor_last_update) {
784
0
    trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
785
0
    istate->cache_changed |= FSMONITOR_CHANGED;
786
0
    FREE_AND_NULL(istate->fsmonitor_last_update);
787
0
  }
788
0
}
789
790
void tweak_fsmonitor(struct index_state *istate)
791
0
{
792
0
  unsigned int i;
793
0
  int fsmonitor_enabled = (fsm_settings__get_mode(istate->repo)
794
0
         > FSMONITOR_MODE_DISABLED);
795
796
0
  if (istate->fsmonitor_dirty) {
797
0
    if (fsmonitor_enabled) {
798
      /* Mark all entries valid */
799
0
      for (i = 0; i < istate->cache_nr; i++) {
800
0
        if (S_ISGITLINK(istate->cache[i]->ce_mode))
801
0
          continue;
802
0
        istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;
803
0
      }
804
805
      /* Mark all previously saved entries as dirty */
806
0
      assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
807
0
      ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);
808
809
0
      refresh_fsmonitor(istate);
810
0
    }
811
812
0
    ewah_free(istate->fsmonitor_dirty);
813
0
    istate->fsmonitor_dirty = NULL;
814
0
  }
815
816
0
  if (fsmonitor_enabled)
817
0
    add_fsmonitor(istate);
818
0
  else
819
0
    remove_fsmonitor(istate);
820
0
}