fsmonitor--daemon: add pathname classification

Teach fsmonitor--daemon to classify relative and absolute
pathnames and decide how they should be handled.  This will
be used by the platform-specific backend to respond to each
filesystem event.

When we register for filesystem notifications on a directory,
we get events for everything (recursively) in the directory.
We want to report to clients changes to tracked and untracked
paths within the working directory proper.  We do not want to
report changes within the .git directory, for example.

This classification will be used in a later commit by the
different backends to classify paths as events are received.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff Hostetler
2022-03-25 18:02:55 +00:00
committed by Junio C Hamano
parent c284e27ba7
commit 0ae7a1d9ab
2 changed files with 168 additions and 0 deletions

View File

@ -134,6 +134,87 @@ static int handle_client(void *data,
return result;
}
#define FSMONITOR_COOKIE_PREFIX ".fsmonitor-daemon-"
enum fsmonitor_path_type fsmonitor_classify_path_workdir_relative(
const char *rel)
{
if (fspathncmp(rel, ".git", 4))
return IS_WORKDIR_PATH;
rel += 4;
if (!*rel)
return IS_DOT_GIT;
if (*rel != '/')
return IS_WORKDIR_PATH; /* e.g. .gitignore */
rel++;
if (!fspathncmp(rel, FSMONITOR_COOKIE_PREFIX,
strlen(FSMONITOR_COOKIE_PREFIX)))
return IS_INSIDE_DOT_GIT_WITH_COOKIE_PREFIX;
return IS_INSIDE_DOT_GIT;
}
enum fsmonitor_path_type fsmonitor_classify_path_gitdir_relative(
const char *rel)
{
if (!fspathncmp(rel, FSMONITOR_COOKIE_PREFIX,
strlen(FSMONITOR_COOKIE_PREFIX)))
return IS_INSIDE_GITDIR_WITH_COOKIE_PREFIX;
return IS_INSIDE_GITDIR;
}
static enum fsmonitor_path_type try_classify_workdir_abs_path(
struct fsmonitor_daemon_state *state,
const char *path)
{
const char *rel;
if (fspathncmp(path, state->path_worktree_watch.buf,
state->path_worktree_watch.len))
return IS_OUTSIDE_CONE;
rel = path + state->path_worktree_watch.len;
if (!*rel)
return IS_WORKDIR_PATH; /* it is the root dir exactly */
if (*rel != '/')
return IS_OUTSIDE_CONE;
rel++;
return fsmonitor_classify_path_workdir_relative(rel);
}
enum fsmonitor_path_type fsmonitor_classify_path_absolute(
struct fsmonitor_daemon_state *state,
const char *path)
{
const char *rel;
enum fsmonitor_path_type t;
t = try_classify_workdir_abs_path(state, path);
if (state->nr_paths_watching == 1)
return t;
if (t != IS_OUTSIDE_CONE)
return t;
if (fspathncmp(path, state->path_gitdir_watch.buf,
state->path_gitdir_watch.len))
return IS_OUTSIDE_CONE;
rel = path + state->path_gitdir_watch.len;
if (!*rel)
return IS_GITDIR; /* it is the <gitdir> exactly */
if (*rel != '/')
return IS_OUTSIDE_CONE;
rel++;
return fsmonitor_classify_path_gitdir_relative(rel);
}
static void *fsm_listen__thread_proc(void *_state)
{
struct fsmonitor_daemon_state *state = _state;