Merge branch 'ps/reftable-drop-generic'
[git/gitster.git] / fsmonitor.c
blob28130f748f7009a1e2ca978c0f17f835f31521b7
1 #define USE_THE_REPOSITORY_VARIABLE
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"
15 #define INDEX_EXTENSION_VERSION1 (1)
16 #define INDEX_EXTENSION_VERSION2 (2)
17 #define HOOK_INTERFACE_VERSION1 (1)
18 #define HOOK_INTERFACE_VERSION2 (2)
20 struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
22 static void assert_index_minimum(struct index_state *istate, size_t pos)
24 if (pos > istate->cache_nr)
25 BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
26 (uintmax_t)pos, istate->cache_nr);
29 static void fsmonitor_ewah_callback(size_t pos, void *is)
31 struct index_state *istate = (struct index_state *)is;
32 struct cache_entry *ce;
34 assert_index_minimum(istate, pos + 1);
36 ce = istate->cache[pos];
37 ce->ce_flags &= ~CE_FSMONITOR_VALID;
40 static int fsmonitor_hook_version(void)
42 int hook_version;
44 if (git_config_get_int("core.fsmonitorhookversion", &hook_version))
45 return -1;
47 if (hook_version == HOOK_INTERFACE_VERSION1 ||
48 hook_version == HOOK_INTERFACE_VERSION2)
49 return hook_version;
51 warning("Invalid hook version '%i' in core.fsmonitorhookversion. "
52 "Must be 1 or 2.", hook_version);
53 return -1;
56 int read_fsmonitor_extension(struct index_state *istate, const void *data,
57 unsigned long sz)
59 const char *index = data;
60 uint32_t hdr_version;
61 uint32_t ewah_size;
62 struct ewah_bitmap *fsmonitor_dirty;
63 int ret;
64 uint64_t timestamp;
65 struct strbuf last_update = STRBUF_INIT;
67 if (sz < sizeof(uint32_t) + 1 + sizeof(uint32_t))
68 return error("corrupt fsmonitor extension (too short)");
70 hdr_version = get_be32(index);
71 index += sizeof(uint32_t);
72 if (hdr_version == INDEX_EXTENSION_VERSION1) {
73 timestamp = get_be64(index);
74 strbuf_addf(&last_update, "%"PRIu64"", timestamp);
75 index += sizeof(uint64_t);
76 } else if (hdr_version == INDEX_EXTENSION_VERSION2) {
77 strbuf_addstr(&last_update, index);
78 index += last_update.len + 1;
79 } else {
80 return error("bad fsmonitor version %d", hdr_version);
83 istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
85 ewah_size = get_be32(index);
86 index += sizeof(uint32_t);
88 fsmonitor_dirty = ewah_new();
89 ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);
90 if (ret != ewah_size) {
91 ewah_free(fsmonitor_dirty);
92 return error("failed to parse ewah bitmap reading fsmonitor index extension");
94 istate->fsmonitor_dirty = fsmonitor_dirty;
96 if (!istate->split_index)
97 assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
99 trace2_data_string("index", NULL, "extension/fsmn/read/token",
100 istate->fsmonitor_last_update);
101 trace_printf_key(&trace_fsmonitor,
102 "read fsmonitor extension successful '%s'",
103 istate->fsmonitor_last_update);
104 return 0;
107 void fill_fsmonitor_bitmap(struct index_state *istate)
109 unsigned int i, skipped = 0;
110 istate->fsmonitor_dirty = ewah_new();
111 for (i = 0; i < istate->cache_nr; i++) {
112 if (istate->cache[i]->ce_flags & CE_REMOVE)
113 skipped++;
114 else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
115 ewah_set(istate->fsmonitor_dirty, i - skipped);
119 void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
121 uint32_t hdr_version;
122 uint32_t ewah_start;
123 uint32_t ewah_size = 0;
124 int fixup = 0;
126 if (!istate->split_index)
127 assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
129 put_be32(&hdr_version, INDEX_EXTENSION_VERSION2);
130 strbuf_add(sb, &hdr_version, sizeof(uint32_t));
132 strbuf_addstr(sb, istate->fsmonitor_last_update);
133 strbuf_addch(sb, 0); /* Want to keep a NUL */
135 fixup = sb->len;
136 strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
138 ewah_start = sb->len;
139 ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
140 ewah_free(istate->fsmonitor_dirty);
141 istate->fsmonitor_dirty = NULL;
143 /* fix up size field */
144 put_be32(&ewah_size, sb->len - ewah_start);
145 memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));
147 trace2_data_string("index", NULL, "extension/fsmn/write/token",
148 istate->fsmonitor_last_update);
149 trace_printf_key(&trace_fsmonitor,
150 "write fsmonitor extension successful '%s'",
151 istate->fsmonitor_last_update);
155 * Call the query-fsmonitor hook passing the last update token of the saved results.
157 static int query_fsmonitor_hook(struct repository *r,
158 int version,
159 const char *last_update,
160 struct strbuf *query_result)
162 struct child_process cp = CHILD_PROCESS_INIT;
163 int result;
165 if (fsm_settings__get_mode(r) != FSMONITOR_MODE_HOOK)
166 return -1;
168 strvec_push(&cp.args, fsm_settings__get_hook_path(r));
169 strvec_pushf(&cp.args, "%d", version);
170 strvec_pushf(&cp.args, "%s", last_update);
171 cp.use_shell = 1;
172 cp.dir = get_git_work_tree();
174 trace2_region_enter("fsm_hook", "query", NULL);
176 result = capture_command(&cp, query_result, 1024);
178 if (result)
179 trace2_data_intmax("fsm_hook", NULL, "query/failed", result);
180 else
181 trace2_data_intmax("fsm_hook", NULL, "query/response-length",
182 query_result->len);
184 trace2_region_leave("fsm_hook", "query", NULL);
186 return result;
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.
195 static void invalidate_ce_fsm(struct cache_entry *ce)
197 if (ce->ce_flags & CE_FSMONITOR_VALID) {
198 trace_printf_key(&trace_fsmonitor,
199 "fsmonitor_refresh_callback INV: '%s'",
200 ce->name);
201 ce->ce_flags &= ~CE_FSMONITOR_VALID;
205 static size_t handle_path_with_trailing_slash(
206 struct index_state *istate, const char *name, int pos);
209 * Use the name-hash to do a case-insensitive cache-entry lookup with
210 * the pathname and invalidate the cache-entry.
212 * Returns the number of cache-entries that we invalidated.
214 static size_t handle_using_name_hash_icase(
215 struct index_state *istate, const char *name)
217 struct cache_entry *ce = NULL;
219 ce = index_file_exists(istate, name, strlen(name), 1);
220 if (!ce)
221 return 0;
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.
232 * Note that we should not have seen FSEvents for a
233 * sparse-index directory, but we handle it just in case.
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.
239 trace_printf_key(&trace_fsmonitor,
240 "fsmonitor_refresh_callback MAP: '%s' '%s'",
241 name, ce->name);
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.
253 untracked_cache_invalidate_trimmed_path(istate, ce->name, 0);
255 invalidate_ce_fsm(ce);
256 return 1;
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.
264 * Returns the number of cache-entries that we invalidated.
266 static size_t handle_using_dir_name_hash_icase(
267 struct index_state *istate, const char *name)
269 struct strbuf canonical_path = STRBUF_INIT;
270 int pos;
271 size_t len = strlen(name);
272 size_t nr_in_cone;
274 if (name[len - 1] == '/')
275 len--;
277 if (!index_dir_find(istate, name, len, &canonical_path))
278 return 0; /* name is untracked */
280 if (!memcmp(name, canonical_path.buf, canonical_path.len)) {
281 strbuf_release(&canonical_path);
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.
292 BUG("handle_using_dir_name_hash_icase(%s) did not exact match",
293 name);
296 trace_printf_key(&trace_fsmonitor,
297 "fsmonitor_refresh_callback MAP: '%s' '%s'",
298 name, canonical_path.buf);
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.
306 strbuf_addch(&canonical_path, '/');
307 pos = index_name_pos(istate, canonical_path.buf,
308 canonical_path.len);
309 nr_in_cone = handle_path_with_trailing_slash(
310 istate, canonical_path.buf, pos);
311 strbuf_release(&canonical_path);
312 return nr_in_cone;
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).
321 * The pathname contains the observed case reported by the FS. We
322 * do not know it is case-correct or -incorrect.
324 * Assume it is case-correct and try an exact match.
326 * Return the number of cache-entries that we invalidated.
328 static size_t handle_path_without_trailing_slash(
329 struct index_state *istate, const char *name, int pos)
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.
339 untracked_cache_invalidate_trimmed_path(istate, name, 0);
341 if (pos >= 0) {
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.)
348 invalidate_ce_fsm(istate->cache[pos]);
349 return 1;
350 } else {
351 size_t nr_in_cone;
352 struct strbuf work_path = STRBUF_INIT;
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.
362 strbuf_add(&work_path, name, strlen(name));
363 strbuf_addch(&work_path, '/');
364 pos = index_name_pos(istate, work_path.buf, work_path.len);
365 nr_in_cone = handle_path_with_trailing_slash(
366 istate, work_path.buf, pos);
367 strbuf_release(&work_path);
368 return nr_in_cone;
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.
377 * The daemon can only reliably do that if the OS FSEvent contains
378 * sufficient information in the event.
380 * macOS FSEvents have enough information.
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)).
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).
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.
404 static size_t handle_path_with_trailing_slash(
405 struct index_state *istate, const char *name, int pos)
407 int i;
408 size_t nr_in_cone = 0;
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.
417 untracked_cache_invalidate_trimmed_path(istate, name, 0);
419 if (pos < 0)
420 pos = -pos - 1;
422 /* Mark all entries for the folder invalid */
423 for (i = pos; i < istate->cache_nr; i++) {
424 if (!starts_with(istate->cache[i]->name, name))
425 break;
426 invalidate_ce_fsm(istate->cache[i]);
427 nr_in_cone++;
430 return nr_in_cone;
433 static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
435 int len = strlen(name);
436 int pos = index_name_pos(istate, name, len);
437 size_t nr_in_cone;
439 trace_printf_key(&trace_fsmonitor,
440 "fsmonitor_refresh_callback '%s' (pos %d)",
441 name, pos);
443 if (name[len - 1] == '/')
444 nr_in_cone = handle_path_with_trailing_slash(istate, name, pos);
445 else
446 nr_in_cone = handle_path_without_trailing_slash(istate, name, pos);
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.
454 if (!nr_in_cone && ignore_case) {
455 nr_in_cone = handle_using_name_hash_icase(istate, name);
456 if (!nr_in_cone)
457 nr_in_cone = handle_using_dir_name_hash_icase(
458 istate, name);
461 if (nr_in_cone)
462 trace_printf_key(&trace_fsmonitor,
463 "fsmonitor_refresh_callback CNT: %d",
464 (int)nr_in_cone);
468 * The number of pathnames that we need to receive from FSMonitor
469 * before we force the index to be updated.
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.
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.
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.
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.
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.
502 static int fsmonitor_force_update_threshold = 100;
504 void refresh_fsmonitor(struct index_state *istate)
506 static int warn_once = 0;
507 struct strbuf query_result = STRBUF_INIT;
508 int query_success = 0, hook_version = -1;
509 size_t bol = 0; /* beginning of line */
510 uint64_t last_update;
511 struct strbuf last_update_token = STRBUF_INIT;
512 char *buf;
513 unsigned int i;
514 int is_trivial = 0;
515 struct repository *r = istate->repo;
516 enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
517 enum fsmonitor_reason reason = fsm_settings__get_reason(r);
519 if (!warn_once && reason > FSMONITOR_REASON_OK) {
520 char *msg = fsm_settings__get_incompatible_msg(r, reason);
521 warn_once = 1;
522 warning("%s", msg);
523 free(msg);
526 if (fsm_mode <= FSMONITOR_MODE_DISABLED ||
527 istate->fsmonitor_has_run_once)
528 return;
530 istate->fsmonitor_has_run_once = 1;
532 trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
534 if (fsm_mode == FSMONITOR_MODE_IPC) {
535 query_success = !fsmonitor_ipc__send_query(
536 istate->fsmonitor_last_update ?
537 istate->fsmonitor_last_update : "builtin:fake",
538 &query_result);
539 if (query_success) {
541 * The response contains a series of nul terminated
542 * strings. The first is the new token.
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()`.
549 buf = query_result.buf;
550 strbuf_addstr(&last_update_token, buf);
551 bol = last_update_token.len + 1;
552 is_trivial = query_result.buf[bol] == '/';
553 if (is_trivial)
554 trace2_data_intmax("fsm_client", NULL,
555 "query/trivial-response", 1);
556 } else {
558 * The builtin daemon is not available on this
559 * platform -OR- we failed to get a response.
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.)
566 strbuf_addstr(&last_update_token, "builtin:fake");
569 goto apply_results;
572 assert(fsm_mode == FSMONITOR_MODE_HOOK);
574 hook_version = fsmonitor_hook_version();
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.
580 last_update = getnanotime();
581 if (hook_version == HOOK_INTERFACE_VERSION1)
582 strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
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.
589 if (istate->fsmonitor_last_update) {
590 if (hook_version == -1 || hook_version == HOOK_INTERFACE_VERSION2) {
591 query_success = !query_fsmonitor_hook(
592 r, HOOK_INTERFACE_VERSION2,
593 istate->fsmonitor_last_update, &query_result);
595 if (query_success) {
596 if (hook_version < 0)
597 hook_version = HOOK_INTERFACE_VERSION2;
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
606 buf = query_result.buf;
607 strbuf_addstr(&last_update_token, buf);
608 if (!last_update_token.len) {
609 warning("Empty last update token.");
610 query_success = 0;
611 } else {
612 bol = last_update_token.len + 1;
613 is_trivial = query_result.buf[bol] == '/';
615 } else if (hook_version < 0) {
616 hook_version = HOOK_INTERFACE_VERSION1;
617 if (!last_update_token.len)
618 strbuf_addf(&last_update_token, "%"PRIu64"", last_update);
622 if (hook_version == HOOK_INTERFACE_VERSION1) {
623 query_success = !query_fsmonitor_hook(
624 r, HOOK_INTERFACE_VERSION1,
625 istate->fsmonitor_last_update, &query_result);
626 if (query_success)
627 is_trivial = query_result.buf[0] == '/';
630 if (is_trivial)
631 trace2_data_intmax("fsm_hook", NULL,
632 "query/trivial-response", 1);
634 trace_performance_since(last_update, "fsmonitor process '%s'",
635 fsm_settings__get_hook_path(r));
636 trace_printf_key(&trace_fsmonitor,
637 "fsmonitor process '%s' returned %s",
638 fsm_settings__get_hook_path(r),
639 query_success ? "success" : "failure");
642 apply_results:
644 * The response from FSMonitor (excluding the header token) is
645 * either:
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.
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.
656 trace2_region_enter("fsmonitor", "apply_results", istate->repo);
658 if (query_success && !is_trivial) {
660 * Mark all pathnames returned by the monitor as dirty.
662 * This updates both the cache-entries and the untracked-cache.
664 int count = 0;
666 buf = query_result.buf;
667 for (i = bol; i < query_result.len; i++) {
668 if (buf[i] != '\0')
669 continue;
670 fsmonitor_refresh_callback(istate, buf + bol);
671 bol = i + 1;
672 count++;
674 if (bol < query_result.len) {
675 fsmonitor_refresh_callback(istate, buf + bol);
676 count++;
679 /* Now mark the untracked cache for fsmonitor usage */
680 if (istate->untracked)
681 istate->untracked->use_fsmonitor = 1;
683 if (count > fsmonitor_force_update_threshold)
684 istate->cache_changed |= FSMONITOR_CHANGED;
686 trace2_data_intmax("fsmonitor", istate->repo, "apply_count",
687 count);
689 } else {
691 * We failed to get a response or received a trivial response,
692 * so invalidate everything.
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.
698 int is_cache_changed = 0;
700 for (i = 0; i < istate->cache_nr; i++) {
701 if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) {
702 is_cache_changed = 1;
703 istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
708 * If we're going to check every file, ensure we save
709 * the results.
711 if (is_cache_changed)
712 istate->cache_changed |= FSMONITOR_CHANGED;
714 if (istate->untracked)
715 istate->untracked->use_fsmonitor = 0;
717 trace2_region_leave("fsmonitor", "apply_results", istate->repo);
719 strbuf_release(&query_result);
721 /* Now that we've updated istate, save the last_update_token */
722 FREE_AND_NULL(istate->fsmonitor_last_update);
723 istate->fsmonitor_last_update = strbuf_detach(&last_update_token, NULL);
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.
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.
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...
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...).
746 * For simplicity, just initialize like we have a V1 process and require
747 * that V2 processes adapt.
749 static void initialize_fsmonitor_last_update(struct index_state *istate)
751 struct strbuf last_update = STRBUF_INIT;
753 strbuf_addf(&last_update, "%"PRIu64"", getnanotime());
754 istate->fsmonitor_last_update = strbuf_detach(&last_update, NULL);
757 void add_fsmonitor(struct index_state *istate)
759 unsigned int i;
761 if (!istate->fsmonitor_last_update) {
762 trace_printf_key(&trace_fsmonitor, "add fsmonitor");
763 istate->cache_changed |= FSMONITOR_CHANGED;
764 initialize_fsmonitor_last_update(istate);
766 /* reset the fsmonitor state */
767 for (i = 0; i < istate->cache_nr; i++)
768 istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
770 /* reset the untracked cache */
771 if (istate->untracked) {
772 add_untracked_cache(istate);
773 istate->untracked->use_fsmonitor = 1;
776 /* Update the fsmonitor state */
777 refresh_fsmonitor(istate);
781 void remove_fsmonitor(struct index_state *istate)
783 if (istate->fsmonitor_last_update) {
784 trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
785 istate->cache_changed |= FSMONITOR_CHANGED;
786 FREE_AND_NULL(istate->fsmonitor_last_update);
790 void tweak_fsmonitor(struct index_state *istate)
792 unsigned int i;
793 int fsmonitor_enabled = (fsm_settings__get_mode(istate->repo)
794 > FSMONITOR_MODE_DISABLED);
796 if (istate->fsmonitor_dirty) {
797 if (fsmonitor_enabled) {
798 /* Mark all entries valid */
799 for (i = 0; i < istate->cache_nr; i++) {
800 if (S_ISGITLINK(istate->cache[i]->ce_mode))
801 continue;
802 istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;
805 /* Mark all previously saved entries as dirty */
806 assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size);
807 ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);
809 refresh_fsmonitor(istate);
812 ewah_free(istate->fsmonitor_dirty);
813 istate->fsmonitor_dirty = NULL;
816 if (fsmonitor_enabled)
817 add_fsmonitor(istate);
818 else
819 remove_fsmonitor(istate);