]> git.ipfire.org Git - thirdparty/git.git/blobdiff - fsmonitor-settings.c
fsmonitor: refactor filesystem checks to common interface
[thirdparty/git.git] / fsmonitor-settings.c
index 464424a1e924c63073a501fc0b9c030904074314..d288cbad479099d5d02fbc5f8ee5f9620d966b00 100644 (file)
@@ -2,6 +2,7 @@
 #include "config.h"
 #include "repository.h"
 #include "fsmonitor-settings.h"
+#include "fsmonitor-path-utils.h"
 
 /*
  * We keep this structure defintion private and have getters
@@ -13,6 +14,52 @@ struct fsmonitor_settings {
        char *hook_path;
 };
 
+/*
+ * Remote working directories are problematic for FSMonitor.
+ *
+ * The underlying file system on the server machine and/or the remote
+ * mount type dictates whether notification events are available at
+ * all to remote client machines.
+ *
+ * Kernel differences between the server and client machines also
+ * dictate the how (buffering, frequency, de-dup) the events are
+ * delivered to client machine processes.
+ *
+ * A client machine (such as a laptop) may choose to suspend/resume
+ * and it is unclear (without lots of testing) whether the watcher can
+ * resync after a resume.  We might be able to treat this as a normal
+ * "events were dropped by the kernel" event and do our normal "flush
+ * and resync" --or-- we might need to close the existing (zombie?)
+ * notification fd and create a new one.
+ *
+ * In theory, the above issues need to be addressed whether we are
+ * using the Hook or IPC API.
+ *
+ * So (for now at least), mark remote working directories as
+ * incompatible unless 'fsmonitor.allowRemote' is true.
+ *
+ */
+#ifdef HAVE_FSMONITOR_OS_SETTINGS
+static enum fsmonitor_reason check_remote(struct repository *r)
+{
+       int allow_remote = -1; /* -1 unset, 0 not allowed, 1 allowed */
+       int is_remote = fsmonitor__is_fs_remote(r->worktree);
+
+       switch (is_remote) {
+               case 0:
+                       return FSMONITOR_REASON_OK;
+               case 1:
+                       repo_config_get_bool(r, "fsmonitor.allowremote", &allow_remote);
+                       if (allow_remote < 1)
+                               return FSMONITOR_REASON_REMOTE;
+                       else
+                               return FSMONITOR_REASON_OK;
+               default:
+                       return FSMONITOR_REASON_ERROR;
+       }
+}
+#endif
+
 static enum fsmonitor_reason check_for_incompatible(struct repository *r)
 {
        if (!r->worktree) {
@@ -27,6 +74,9 @@ static enum fsmonitor_reason check_for_incompatible(struct repository *r)
        {
                enum fsmonitor_reason reason;
 
+               reason = check_remote(r);
+               if (reason != FSMONITOR_REASON_OK)
+                       return reason;
                reason = fsm_os__incompatible(r);
                if (reason != FSMONITOR_REASON_OK)
                        return reason;