aboutsummaryrefslogtreecommitdiffstats
path: root/fsmonitor.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2022-06-10 15:04:14 -0700
committerJunio C Hamano <gitster@pobox.com>2022-06-10 15:04:15 -0700
commit9e496fffc872b20a147d7b80330335edfff919cc (patch)
tree5fba6f05485f020f71ff77d6b4a2d108d4f87ddc /fsmonitor.c
parentMerge branch 'gc/zero-length-branch-config-fix' (diff)
parentt7527: improve implicit shutdown testing in fsmonitor--daemon (diff)
downloadgit-9e496fffc872b20a147d7b80330335edfff919cc.tar.gz
git-9e496fffc872b20a147d7b80330335edfff919cc.zip
Merge branch 'jh/builtin-fsmonitor-part3'
More fsmonitor--daemon. * jh/builtin-fsmonitor-part3: (30 commits) t7527: improve implicit shutdown testing in fsmonitor--daemon fsmonitor--daemon: allow --super-prefix argument t7527: test Unicode NFC/NFD handling on MacOS t/lib-unicode-nfc-nfd: helper prereqs for testing unicode nfc/nfd t/helper/hexdump: add helper to print hexdump of stdin fsmonitor: on macOS also emit NFC spelling for NFD pathname t7527: test FSMonitor on case insensitive+preserving file system fsmonitor: never set CE_FSMONITOR_VALID on submodules t/perf/p7527: add perf test for builtin FSMonitor t7527: FSMonitor tests for directory moves fsmonitor: optimize processing of directory events fsm-listen-darwin: shutdown daemon if worktree root is moved/renamed fsm-health-win32: force shutdown daemon if worktree root moves fsm-health-win32: add polling framework to monitor daemon health fsmonitor--daemon: stub in health thread fsmonitor--daemon: rename listener thread related variables fsmonitor--daemon: prepare for adding health thread fsmonitor--daemon: cd out of worktree root fsm-listen-darwin: ignore FSEvents caused by xattr changes on macOS unpack-trees: initialize fsmonitor_has_run_once in o->result ...
Diffstat (limited to 'fsmonitor.c')
-rw-r--r--fsmonitor.c73
1 files changed, 56 insertions, 17 deletions
diff --git a/fsmonitor.c b/fsmonitor.c
index 292a6742b4..57d6a483be 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c
@@ -184,30 +184,68 @@ static int query_fsmonitor_hook(struct repository *r,
static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
{
int i, len = strlen(name);
- if (name[len - 1] == '/') {
+ int pos = index_name_pos(istate, name, len);
+
+ trace_printf_key(&trace_fsmonitor,
+ "fsmonitor_refresh_callback '%s' (pos %d)",
+ name, pos);
+ if (name[len - 1] == '/') {
/*
- * TODO We should binary search to find the first path with
- * TODO this directory prefix. Then linearly update entries
- * TODO while the prefix matches. Taking care to search without
- * TODO the trailing slash -- because '/' sorts after a few
- * TODO interesting special chars, like '.' and ' '.
+ * The daemon can decorate directory events, such as
+ * moves or renames, with a trailing slash if the OS
+ * FS Event contains sufficient information, such as
+ * MacOS.
+ *
+ * Use this to invalidate the entire cone under that
+ * directory.
+ *
+ * We do not expect an exact match because the index
+ * does not normally contain directory entries, so we
+ * start at the insertion point and scan.
*/
+ if (pos < 0)
+ pos = -pos - 1;
/* Mark all entries for the folder invalid */
- for (i = 0; i < istate->cache_nr; i++) {
- if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID &&
- starts_with(istate->cache[i]->name, name))
- istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
+ for (i = pos; i < istate->cache_nr; i++) {
+ if (!starts_with(istate->cache[i]->name, name))
+ break;
+ istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
}
- /* Need to remove the / from the path for the untracked cache */
+
+ /*
+ * We need to remove the traling "/" from the path
+ * for the untracked cache.
+ */
name[len - 1] = '\0';
+ } else if (pos >= 0) {
+ /*
+ * We have an exact match for this path and can just
+ * invalidate it.
+ */
+ istate->cache[pos]->ce_flags &= ~CE_FSMONITOR_VALID;
} else {
- int pos = index_name_pos(istate, name, strlen(name));
-
- if (pos >= 0) {
- struct cache_entry *ce = istate->cache[pos];
- ce->ce_flags &= ~CE_FSMONITOR_VALID;
+ /*
+ * The path is not a tracked file -or- it is a
+ * directory event on a platform that cannot
+ * distinguish between file and directory events in
+ * the event handler, such as Windows.
+ *
+ * Scan as if it is a directory and invalidate the
+ * cone under it. (But remember to ignore items
+ * between "name" and "name/", such as "name-" and
+ * "name.".
+ */
+ pos = -pos - 1;
+
+ for (i = pos; i < istate->cache_nr; i++) {
+ if (!starts_with(istate->cache[i]->name, name))
+ break;
+ if ((unsigned char)istate->cache[i]->name[len] > '/')
+ break;
+ if (istate->cache[i]->name[len] == '/')
+ istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
}
}
@@ -215,7 +253,6 @@ static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
* Mark the untracked cache dirty even if it wasn't found in the index
* as it could be a new untracked file.
*/
- trace_printf_key(&trace_fsmonitor, "fsmonitor_refresh_callback '%s'", name);
untracked_cache_invalidate_path(istate, name, 0);
}
@@ -543,6 +580,8 @@ void tweak_fsmonitor(struct index_state *istate)
if (fsmonitor_enabled) {
/* Mark all entries valid */
for (i = 0; i < istate->cache_nr; i++) {
+ if (S_ISGITLINK(istate->cache[i]->ce_mode))
+ continue;
istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;
}