fsmonitor: Implement fsmonitor for Linux#1352
fsmonitor: Implement fsmonitor for Linux#1352edecosta-mw wants to merge 6 commits intogit:mastergit/git:masterfrom
Conversation
|
There are issues in commit 39f88e5: |
8622a77 to
20f3e77
Compare
|
There are issues in commit c74ffa4: |
73d2435 to
77ed35b
Compare
|
/submit |
|
Submitted as pull.1352.git.git.1665326258.gitgitgadget@gmail.com To fetch this version into To fetch this version to local tag |
|
This branch is now known as |
|
This patch series was integrated into seen via 529e7ca. |
|
On the Git mailing list, Junio C Hamano wrote (reply to this): "Eric DeCosta via GitGitGadget" <gitgitgadget@gmail.com> writes:
> Goal is to deliver fsmonitor for Linux that is on par with fsmonitor for
> Windows and Mac OS.
>
> This patch set builds upon previous work for done for Windows and Mac OS
> (first 6 patches) ...
For those who are watching from sidelines...
The Windows part is already in Git 2.38; the changes needed for
macOS are already in 'next' and the first 6 patches in this 12-patch
series are identical to them. The patches 7-12 are new.
> to implement a fsmonitor back-end for Linux based on the
> Linux inotify API. inotify differs significantly from the equivalent Windows
> and Mac OS APIs in that a watch must be registered for every directory of
> interest (rather than a singular watch at the root of the directory tree)
> and special care must be taken to handle directory renames correctly.
|
|
On the Git mailing list, Eric Sunshine wrote (reply to this): On Sun, Oct 9, 2022 at 7:55 PM Junio C Hamano <gitster@pobox.com> wrote:
> "Eric DeCosta via GitGitGadget" <gitgitgadget@gmail.com> writes:
> > Goal is to deliver fsmonitor for Linux that is on par with fsmonitor for
> > Windows and Mac OS.
> >
> > This patch set builds upon previous work for done for Windows and Mac OS
> > (first 6 patches) ...
>
> For those who are watching from sidelines...
>
> The Windows part is already in Git 2.38; the changes needed for
> macOS are already in 'next' and the first 6 patches in this 12-patch
> series are identical to them. The patches 7-12 are new.
Thanks for clarifying. I found it confusing that there were a number
of patches in this series which I had already seen despite the cover
letter's claim that this series builds upon "previous work". Thus, it
wasn't clear whether this series was a reroll (refining some
already-seen patches) with additional patches for Linux, or if it was
purely new work with the original patches included by accident[1].
[1]: In the few times I've used GitGitGadget, I've had to jump through
hoops to make it send just the "new" patches when I've built a series
atop some other series only in 'next' or 'seen', so I can understand
the inclusion of the first six patches being accidental. (Regarding
the hoop-jumping, it may be that I just don't understand how to "work"
GitGitGadget or GitHub pull-requests.) |
|
User |
| @@ -0,0 +1,163 @@ | ||
| #include "fsmonitor.h" |
There was a problem hiding this comment.
On the Git mailing list, Ævar Arnfjörð Bjarmason wrote (reply to this):
On Sun, Oct 09 2022, Eric DeCosta via GitGitGadget wrote:
> From: Eric DeCosta <edecosta@mathworks.com>
>
> Compare the given path to the mounted filesystems. Find the mount that is
> the longest prefix of the path (if any) and determine if that mount is on a
> local or remote filesystem.
>
> Signed-off-by: Eric DeCosta <edecosta@mathworks.com>
> ---
> compat/fsmonitor/fsm-path-utils-linux.c | 163 ++++++++++++++++++++++++
> 1 file changed, 163 insertions(+)
> create mode 100644 compat/fsmonitor/fsm-path-utils-linux.c
>
> diff --git a/compat/fsmonitor/fsm-path-utils-linux.c b/compat/fsmonitor/fsm-path-utils-linux.c
> new file mode 100644
> index 00000000000..369692a788f
> --- /dev/null
> +++ b/compat/fsmonitor/fsm-path-utils-linux.c
> @@ -0,0 +1,163 @@
> +#include "fsmonitor.h"
> +#include "fsmonitor-path-utils.h"
> +#include <errno.h>
> +#include <mntent.h>
> +#include <sys/mount.h>
> +#include <sys/statvfs.h>
> +
> +/*
> + * https://github.com/coreutils/gnulib/blob/master/lib/mountlist.c
> + */
> +#ifndef ME_REMOTE
> +/* A file system is "remote" if its Fs_name contains a ':'
> + or if (it is of type (smbfs or cifs) and its Fs_name starts with '//')
> + or if it is of any other of the listed types
> + or Fs_name is equal to "-hosts" (used by autofs to mount remote fs).
> + "VM" file systems like prl_fs or vboxsf are not considered remote here. */
> +# define ME_REMOTE(Fs_name, Fs_type) \
> + (strchr (Fs_name, ':') != NULL \
> + || ((Fs_name)[0] == '/' \
> + && (Fs_name)[1] == '/' \
> + && (strcmp (Fs_type, "smbfs") == 0 \
> + || strcmp (Fs_type, "smb3") == 0 \
> + || strcmp (Fs_type, "cifs") == 0)) \
> + || strcmp (Fs_type, "acfs") == 0 \
> + || strcmp (Fs_type, "afs") == 0 \
> + || strcmp (Fs_type, "coda") == 0 \
> + || strcmp (Fs_type, "auristorfs") == 0 \
> + || strcmp (Fs_type, "fhgfs") == 0 \
> + || strcmp (Fs_type, "gpfs") == 0 \
> + || strcmp (Fs_type, "ibrix") == 0 \
> + || strcmp (Fs_type, "ocfs2") == 0 \
> + || strcmp (Fs_type, "vxfs") == 0 \
> + || strcmp ("-hosts", Fs_name) == 0)
> +#endif
So, this is just copy/pasted GPLv3 code into our GPLv2-only codebase?:
https://github.com/coreutils/gnulib/blob/cd1fdabe8b66c102124b6a5b0c97dded20246b46/lib/mountlist.c#L230-L247
> +static struct mntent *find_mount(const char *path, const struct statvfs *fs)
> +{
> + const char *const mounts = "/proc/mounts";
> + const char *rp = real_pathdup(path, 1);
> + struct mntent *ment = NULL;
> + struct mntent *found = NULL;
> + struct statvfs mntfs;
> + FILE *fp;
> + int dlen, plen, flen = 0;
> +
> + fp = setmntent(mounts, "r");
> + if (!fp) {
> + error_errno(_("setmntent('%s') failed"), mounts);
> + return NULL;
This code would probably be nicer if you returned int, and passed a
pointer to a struct to populate as a paremeter. Then you could just
"return error..." for this and the below cases.
> + }
> +
> + plen = strlen(rp);
> +
> + /* read all the mount information and compare to path */
> + while ((ment = getmntent(fp)) != NULL) {
> + if (statvfs(ment->mnt_dir, &mntfs)) {
> + switch (errno) {
> + case EPERM:
> + case ESRCH:
> + case EACCES:
> + continue;
> + default:
> + error_errno(_("statvfs('%s') failed"), ment->mnt_dir);
> + endmntent(fp);is
> + return NULL;
> + }
> + }
> +
> + /* is mount on the same filesystem and is a prefix of the path */
> + if ((fs->f_fsid == mntfs.f_fsid) &&
> + !strncmp(ment->mnt_dir, rp, strlen(ment->mnt_dir))) {
> + dlen = strlen(ment->mnt_dir);
> + if (dlen > plen)
> + continue;
> + /*
> + * root is always a potential match; otherwise look for
> + * directory prefix
> + */
> + if ((dlen == 1 && ment->mnt_dir[0] == '/') ||
> + (dlen > flen && (!rp[dlen] || rp[dlen] == '/'))) {
> + flen = dlen;
> + /*
> + * https://man7.org/linux/man-pages/man3/getmntent.3.html
> + *
> + * The pointer points to a static area of memory which is
> + * overwritten by subsequent calls to getmntent().
> + */
> + if (!found)
> + CALLOC_ARRAY(found, 1);
It seems we never populate >1 of these, so don't you just want
xmalloc(). Or actually...
> + free(found->mnt_dir);
> + free(found->mnt_type);
> + free(found->mnt_fsname);
> + found->mnt_dir = xmemdupz(ment->mnt_dir, strlen(ment->mnt_dir));
> + found->mnt_type = xmemdupz(ment->mnt_type, strlen(ment->mnt_type));
> + found->mnt_fsname = xmemdupz(ment->mnt_fsname, strlen(ment->mnt_fsname));
Don't mix mem*() and str*(). In this case we need the string to be '\0'
delimited, so use xstrndup().
And once we do that, we might wonder why we're explicitly finding the
'\0', just to pass it to the xstrn*() function, when we can just do:
found->mnt_dir = xstrdup(ment->mnt_dir);
...
Which would AFAICT be equivalent to what you're doing here.
> + }
> + }
> + }
> + endmntent(fp);
> +
> + return found;
> +}
> +
> +int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info)
> +{
> + struct mntent *ment;
...make this (or above) a "struct mntent ment", then pass &ment down, so
we can fill that struct? Dunno...
> + struct statvfs fs;
> +
> + if (statvfs(path, &fs))
> + return error_errno(_("statvfs('%s') failed"), path);
> +
> + ment = find_mount(path, &fs);
> + if (!ment)
> + return -1;
> +
> + trace_printf_key(&trace_fsmonitor,
> + "statvfs('%s') [flags 0x%08lx] '%s' '%s'",
> + path, fs.f_flag, ment->mnt_type, ment->mnt_fsname);
> +
> + if (ME_REMOTE(ment->mnt_fsname, ment->mnt_type))
> + fs_info->is_remote = 1;
> + else
> + fs_info->is_remote = 0;
Shorter:
fs_info->is_remote = ME_REMOTE(ment->mnt_fsname, ment->mnt_type);There was a problem hiding this comment.
On the Git mailing list, Eric DeCosta wrote (reply to this):
> -----Original Message-----
> From: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> Sent: Monday, October 10, 2022 6:04 AM
> To: Eric DeCosta via GitGitGadget <gitgitgadget@gmail.com>
> Cc: git@vger.kernel.org; Eric DeCosta <edecosta@mathworks.com>
> Subject: Re: [PATCH 08/12] fsmonitor: determine if filesystem is local or
> remote
>
>
> On Sun, Oct 09 2022, Eric DeCosta via GitGitGadget wrote:
>
> > From: Eric DeCosta <edecosta@mathworks.com>
> >
> > Compare the given path to the mounted filesystems. Find the mount that
> > is the longest prefix of the path (if any) and determine if that mount
> > is on a local or remote filesystem.
> >
> > Signed-off-by: Eric DeCosta <edecosta@mathworks.com>
> > ---
> > compat/fsmonitor/fsm-path-utils-linux.c | 163
> ++++++++++++++++++++++++
> > 1 file changed, 163 insertions(+)
> > create mode 100644 compat/fsmonitor/fsm-path-utils-linux.c
> >
> > diff --git a/compat/fsmonitor/fsm-path-utils-linux.c
> > b/compat/fsmonitor/fsm-path-utils-linux.c
> > new file mode 100644
> > index 00000000000..369692a788f
> > --- /dev/null
> > +++ b/compat/fsmonitor/fsm-path-utils-linux.c
> > @@ -0,0 +1,163 @@
> > +#include "fsmonitor.h"
> > +#include "fsmonitor-path-utils.h"
> > +#include <errno.h>
> > +#include <mntent.h>
> > +#include <sys/mount.h>
> > +#include <sys/statvfs.h>
> > +
> > +/*
> > + * https://github.com/coreutils/gnulib/blob/master/lib/mountlist.c
> > +<https://protect-
> us.mimecast.com/s/wKJsC9rj7lc3WKmYUOq9E9?domain=gith
> > +ub.com>
> > + */
> > +#ifndef ME_REMOTE
> > +/* A file system is "remote" if its Fs_name contains a ':'
> > + or if (it is of type (smbfs or cifs) and its Fs_name starts with
> > +'//') or if it is of any other of the listed types or Fs_name is
> > +equal to "-hosts" (used by autofs to mount remote fs).
> > + "VM" file systems like prl_fs or vboxsf are not considered remote
> > +here. */ # define ME_REMOTE(Fs_name, Fs_type) \ (strchr (Fs_name,
> > +':') != NULL \
> > + || ((Fs_name)[0] == '/' \
> > + && (Fs_name)[1] == '/' \
> > + && (strcmp (Fs_type, "smbfs") == 0 \
> > + || strcmp (Fs_type, "smb3") == 0 \
> > + || strcmp (Fs_type, "cifs") == 0)) \ strcmp (Fs_type, "acfs") == 0 \
> > + || strcmp (Fs_type, "afs") == 0 \ strcmp (Fs_type, "coda") == 0 \
> > + || strcmp (Fs_type, "auristorfs") == 0 \ strcmp (Fs_type, "fhgfs")
> > + || == 0 \ strcmp (Fs_type, "gpfs") == 0 \ strcmp (Fs_type, "ibrix")
> > + || == 0 \ strcmp (Fs_type, "ocfs2") == 0 \ strcmp (Fs_type, "vxfs")
> > + || == 0 \ strcmp ("-hosts", Fs_name) == 0)
> > +#endif
>
> So, this is just copy/pasted GPLv3 code into our GPLv2-only codebase?:
> https://github.com/coreutils/gnulib/blob/cd1fdabe8b66c102124b6a5b0c97d
> ded20246b46/lib/mountlist.c#L230-L247 <https://protect-
> us.mimecast.com/s/zxPbC0RMy1hoXW2rCOSXJD?domain=github.com>
>
Yes. I was hoping for some guidance as to what to do with ME_REMOTE.
I also found it, verbatim, here in midnight commander:
https://github.com/MidnightCommander/mc/blob/e48cd98ac13a9b4366bd88287f632413766b967f/src/filemanager/mountlist.c#L258-L281
But that's just another GPLv3 code base.
> > +static struct mntent *find_mount(const char *path, const struct
> > +statvfs *fs) { const char *const mounts = "/proc/mounts"; const
> > +char *rp = real_pathdup(path, 1); struct mntent *ment = NULL;
> > +struct mntent *found = NULL; struct statvfs mntfs; FILE *fp; int
> > +dlen, plen, flen = 0;
> > +
> > + fp = setmntent(mounts, "r");
> > + if (!fp) {
> > + error_errno(_("setmntent('%s') failed"), mounts); return NULL;
>
> This code would probably be nicer if you returned int, and passed a pointer
> to a struct to populate as a paremeter. Then you could just "return error..."
> for this and the below cases.
>
> > + }
> > +
> > + plen = strlen(rp);
> > +
> > + /* read all the mount information and compare to path */ while
> > + ((ment = getmntent(fp)) != NULL) { if (statvfs(ment->mnt_dir,
> > + &mntfs)) { switch (errno) { case EPERM:
> > + case ESRCH:
> > + case EACCES:
> > + continue;
> > + default:
> > + error_errno(_("statvfs('%s') failed"), ment->mnt_dir);
> > + endmntent(fp);is return NULL; } }
> > +
> > + /* is mount on the same filesystem and is a prefix of the path */ if
> > + ((fs->f_fsid == mntfs.f_fsid) && !strncmp(ment->mnt_dir, rp,
> > + strlen(ment->mnt_dir))) { dlen = strlen(ment->mnt_dir); if (dlen >
> > + plen) continue;
> > + /*
> > + * root is always a potential match; otherwise look for
> > + * directory prefix
> > + */
> > + if ((dlen == 1 && ment->mnt_dir[0] == '/') || (dlen > flen &&
> > + (!rp[dlen] || rp[dlen] == '/'))) { flen = dlen;
> > + /*
> > + * https://man7.org/linux/man-pages/man3/getmntent.3.html
> > + <https://protect-
> us.mimecast.com/s/aOmSCgJyVrT01WlYc76tSR?domain=man
> > + 7.org>
> > + *
> > + * The pointer points to a static area of memory which is
> > + * overwritten by subsequent calls to getmntent().
> > + */
> > + if (!found)
> > + CALLOC_ARRAY(found, 1);
>
> It seems we never populate >1 of these, so don't you just want xmalloc(). Or
> actually...
>
> > + free(found->mnt_dir);
> > + free(found->mnt_type);
> > + free(found->mnt_fsname);
> > + found->mnt_dir = xmemdupz(ment->mnt_dir, strlen(ment->mnt_dir));
> > + found->mnt_type = xmemdupz(ment->mnt_type, strlen(ment-
> >mnt_type));
> > + found->mnt_fsname = xmemdupz(ment->mnt_fsname,
> > + found->strlen(ment->mnt_fsname));
>
> Don't mix mem*() and str*(). In this case we need the string to be '\0'
> delimited, so use xstrndup().
>
> And once we do that, we might wonder why we're explicitly finding the '\0',
> just to pass it to the xstrn*() function, when we can just do:
>
> found->mnt_dir = xstrdup(ment->mnt_dir);
> ...
>
> Which would AFAICT be equivalent to what you're doing here.
>
> > + }
> > + }
> > + }
> > + endmntent(fp);
> > +
> > + return found;
> > +}
> > +
> > +int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info)
> > +{ struct mntent *ment;
>
> ...make this (or above) a "struct mntent ment", then pass &ment down, so
> we can fill that struct? Dunno...
>
> > + struct statvfs fs;
> > +
> > + if (statvfs(path, &fs))
> > + return error_errno(_("statvfs('%s') failed"), path);
> > +
> > + ment = find_mount(path, &fs);
> > + if (!ment)
> > + return -1;
> > +
> > + trace_printf_key(&trace_fsmonitor,
> > + "statvfs('%s') [flags 0x%08lx] '%s' '%s'", path, fs.f_flag,
> > + ment->mnt_type, ment->mnt_fsname);
> > +
> > + if (ME_REMOTE(ment->mnt_fsname, ment->mnt_type)) fs_info-
> >is_remote
> > + = 1; else fs_info->is_remote = 0;
>
> Shorter:
>
> fs_info->is_remote = ME_REMOTE(ment->mnt_fsname, ment->mnt_type);
|
User |
|
On the Git mailing list, Junio C Hamano wrote (reply to this): "Eric DeCosta via GitGitGadget" <gitgitgadget@gmail.com> writes:
> Goal is to deliver fsmonitor for Linux that is on par with fsmonitor for
> Windows and Mac OS.
>
> This patch set builds upon previous work for done for Windows and Mac OS
> (first 6 patches) to implement a fsmonitor back-end for Linux based on the
> Linux inotify API. inotify differs significantly from the equivalent Windows
> and Mac OS APIs in that a watch must be registered for every directory of
> interest (rather than a singular watch at the root of the directory tree)
> and special care must be taken to handle directory renames correctly.
I am seeing occasional breakages of t7527.16 that does not seem to
reproduce reliably. |
|
There was a status update in the "New Topics" section about the branch Bundled fsmonitor for Linux using inotify API. Needs review. source: <pull.1326.v15.git.1664904751.gitgitgadget@gmail.com> source: <pull.1352.git.git.1665326258.gitgitgadget@gmail.com> |
ac2c20f to
4a4dfd1
Compare
|
@edecosta-mw The build failure seems to be due to the massive diff --git a/compat/fsmonitor/fsm-health-linux.c b/compat/fsmonitor/fsm-health-linux.c
index b9f709e8548..4c291f8a066 100644
--- a/compat/fsmonitor/fsm-health-linux.c
+++ b/compat/fsmonitor/fsm-health-linux.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "fsmonitor.h"
#include "fsm-health.h"
diff --git a/compat/fsmonitor/fsm-ipc-unix.c b/compat/fsmonitor/fsm-ipc-unix.c
index eb25123fa12..597162b569b 100644
--- a/compat/fsmonitor/fsm-ipc-unix.c
+++ b/compat/fsmonitor/fsm-ipc-unix.c
@@ -1,7 +1,9 @@
-#include "cache.h"
+#include "git-compat-util.h"
#include "config.h"
#include "hex.h"
#include "strbuf.h"
+#include "path.h"
+#include "gettext.h"
#include "fsmonitor.h"
#include "fsmonitor-ipc.h"
#include "fsmonitor-path-utils.h"
@@ -38,9 +40,10 @@ const char *fsmonitor_ipc__get_path(struct repository *r)
/* Create the socket file in either socketDir or $HOME */
if (sock_dir && *sock_dir) {
strbuf_addf(&ipc_file, "%s/.git-fsmonitor-%s",
- sock_dir, hash_to_hex(hash));
+ sock_dir, hash_to_hex_algop(hash, r->hash_algo));
} else {
- strbuf_addf(&ipc_file, "~/.git-fsmonitor-%s", hash_to_hex(hash));
+ strbuf_addf(&ipc_file, "~/.git-fsmonitor-%s",
+ hash_to_hex_algop(hash, r->hash_algo));
}
free(sock_dir);
diff --git a/compat/fsmonitor/fsm-listen-linux.c b/compat/fsmonitor/fsm-listen-linux.c
index e8548e4e009..5a334ce1e89 100644
--- a/compat/fsmonitor/fsm-listen-linux.c
+++ b/compat/fsmonitor/fsm-listen-linux.c
@@ -1,4 +1,7 @@
-#include "cache.h"
+#include "git-compat-util.h"
+#include "gettext.h"
+#include "string-list.h"
+#include "simple-ipc.h"
#include "fsmonitor.h"
#include "fsm-listen.h"
#include "fsmonitor--daemon.h"
diff --git a/compat/fsmonitor/fsm-path-utils-linux.c b/compat/fsmonitor/fsm-path-utils-linux.c
index c21d1349532..c6be61d95cf 100644
--- a/compat/fsmonitor/fsm-path-utils-linux.c
+++ b/compat/fsmonitor/fsm-path-utils-linux.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "abspath.h"
+#include "gettext.h"
#include "fsmonitor.h"
#include "fsmonitor-path-utils.h"
#include "fsm-path-utils-linux.h"
diff --git a/compat/fsmonitor/fsm-settings-unix.c b/compat/fsmonitor/fsm-settings-unix.c
index d16dca89416..80683aafb5b 100644
--- a/compat/fsmonitor/fsm-settings-unix.c
+++ b/compat/fsmonitor/fsm-settings-unix.c
@@ -1,3 +1,4 @@
+#include "git-compat-util.h"
#include "fsmonitor.h"
#include "fsmonitor-ipc.h"
#include "fsmonitor-path-utils.h" |
|
@edecosta-mw did my suggestion help? |
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Based on work from git#1352 by Eric DeCosta, updated to work with the current codebase. Signed-off-by: Claude <noreply@anthropic.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Based on work from git#1352 by Eric DeCosta, updated to work with the current codebase. Signed-off-by: Claude <noreply@anthropic.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Based on work from git#1352 by Eric DeCosta, updated to work with the current codebase. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Based on work from git#1352 by Eric DeCosta, updated to work with the current codebase. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags (NO_CURL, NO_GETTEXT, NO_TCLTK) - Build succeeds with SANITIZE=address (AddressSanitizer) - General tests pass (t0001-init, t3200-branch, etc.) - fsmonitor tests require local filesystem (v9fs test environment is correctly detected as remote and rejected) - Manual testing confirms daemon starts and monitors filesystem when configured with fsmonitor.allowremote=true and fsmonitor.socketdir pointing to a local filesystem (tmpfs) Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags (NO_CURL, NO_GETTEXT, NO_TCLTK) - Build succeeds with SANITIZE=address (AddressSanitizer) - General tests pass (t0001-init, t3200-branch, etc.) - fsmonitor tests require local filesystem (v9fs test environment is correctly detected as remote and rejected) - Manual testing confirms daemon starts and monitors filesystem when configured with fsmonitor.allowremote=true and fsmonitor.socketdir pointing to a local filesystem (tmpfs) Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags (NO_CURL, NO_GETTEXT, NO_TCLTK) - Build succeeds with SANITIZE=address (AddressSanitizer) - General tests pass (t0001-init, t3200-branch, etc.) - fsmonitor tests require local filesystem (v9fs test environment is correctly detected as remote and rejected) - Manual testing confirms daemon starts and monitors filesystem when configured with fsmonitor.allowremote=true and fsmonitor.socketdir pointing to a local filesystem (tmpfs) Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags (NO_CURL, NO_GETTEXT, NO_TCLTK) - Build succeeds with SANITIZE=address (AddressSanitizer) - General tests pass (t0001-init, t3200-branch, etc.) - fsmonitor tests require local filesystem (v9fs test environment is correctly detected as remote and rejected) - Manual testing confirms daemon starts and monitors filesystem when configured with fsmonitor.allowremote=true and fsmonitor.socketdir pointing to a local filesystem (tmpfs) Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags (NO_CURL, NO_GETTEXT, NO_TCLTK) - Build succeeds with SANITIZE=address (AddressSanitizer) - All 68 tests in t7527-builtin-fsmonitor.sh pass on tmpfs - Test 18 "flush cached data" specifically validates that sequence numbers are correctly maintained after flush operations - Daemon correctly starts, monitors file events (IN_CREATE, IN_MODIFY, IN_DELETE, IN_MOVED_FROM/TO), and responds to client queries - Remote filesystem detection works correctly (v9fs, NFS, CIFS, etc. are properly identified and rejected unless allowRemote is set) - Manual testing confirms proper cookie synchronization between client and daemon Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Additional fix for test compatibility: - Lazy batch creation: Only create fsmonitor_batch when processing actual workdir path events, not for cookie events. This prevents empty batches from incrementing the sequence number, which caused t7527.18 "flush cached data" to fail. Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR #1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR #1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from #1352 by Eric DeCosta, and #1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote - Creates batches lazily (only for actual file events, not cookies) to avoid spurious sequence number increments Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Testing performed: - Build succeeds with standard flags and SANITIZE=address - All t7527-builtin-fsmonitor.sh tests pass on local filesystems - Remote filesystem detection correctly rejects network mounts Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection - Meson build support included Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Additional fixes: - Fixed memory leak: Added hashmap_clear(&state.cookies) in cleanup section of fsmonitor_run_daemon() - Fixed khash memory leak in do_handle_client() by using kh_destroy_str() - Removed 9p (Plan 9) from remote filesystem list since inotify works correctly on 9p filesystems - Handle EEXIST in inotify_add_watch() for race conditions during rapid directory creation Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection - Meson build support included Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Additional fixes: - Fixed memory leak: Added hashmap_clear(&state.cookies) in cleanup section of fsmonitor_run_daemon() - Fixed khash memory leak in do_handle_client() by using kh_destroy_str() - Removed 9p (Plan 9) from remote filesystem list since inotify works correctly on 9p filesystems - Handle EEXIST in inotify_add_watch() for race conditions during rapid directory creation Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection - Meson build support included Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Additional fixes: - Fixed memory leak: Added hashmap_clear(&state.cookies) in cleanup section of fsmonitor_run_daemon() - Fixed khash memory leak in do_handle_client() by using kh_destroy_str() - Removed 9p (Plan 9) from remote filesystem list since inotify works correctly on 9p filesystems - Handle EEXIST in inotify_add_watch() for race conditions during rapid directory creation Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection - Meson build support included Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Additional fixes: - Fixed memory leak: Added hashmap_clear(&state.cookies) in cleanup section of fsmonitor_run_daemon() - Fixed khash memory leak in do_handle_client() by using kh_destroy_str() - Removed 9p (Plan 9) from remote filesystem list since inotify works correctly on 9p filesystems - Handle EEXIST in inotify_add_watch() for race conditions during rapid directory creation Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR git#1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR git#1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from git#1352 by Eric DeCosta, and git#1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com>
Implement fsmonitor for Linux using the inotify API, bringing it to feature parity with existing Windows and macOS implementations. The Linux implementation uses inotify to monitor filesystem events. Unlike macOS's FSEvents which can watch a single root directory, inotify requires registering watches on every directory of interest. The implementation carefully handles directory renames and moves using inotify's cookie mechanism to track IN_MOVED_FROM/IN_MOVED_TO event pairs. Key implementation details: - Uses inotify_init1(O_NONBLOCK) for non-blocking event monitoring - Maintains bidirectional hashmaps between watch descriptors and paths for efficient event processing - Handles directory creation, deletion, and renames dynamically - Detects remote filesystems (NFS, CIFS, SMB, etc.) via statfs() - Falls back to $HOME/.git-fsmonitor-* for socket when .git is remote Build configuration: - Enabled via FSMONITOR_DAEMON_BACKEND=linux and FSMONITOR_OS_SETTINGS=linux - Requires NO_PTHREADS and NO_UNIX_SOCKETS to be unset - Adds HAVE_LINUX_MAGIC_H for filesystem type detection Documentation updated to note that fsmonitor.socketDir is now supported on both Mac OS and Linux, and adds a section about inotify watch limits. Issues addressed from PR #1352 (git/git) review comments: - GPLv3 ME_REMOTE macro: Rewrote remote filesystem detection from scratch using statfs() and linux/magic.h constants (no GPLv3 code) - Memory leak on inotify_init1 failure: Added FREE_AND_NULL cleanup - Unsafe hashmap iteration in dtor: Collect entries first, then modify - Missing null checks in stop_async: Added proper guard conditions - dirname() modifying argument: Create copy with xstrdup() first - Non-portable f_fsid.__val: Use memcmp() for fsid comparison - Missing worktree null check: Added BUG() for null worktree - Header updates: Use git-compat-util.h, hash_to_hex_algop() - Code style: Use xstrdup() not xmemdupz(), proper pointer style Issues addressed from PR #1667 (git/git) review comments: - EINTR handling: read() now handles both EAGAIN and EINTR - Trailing pipe in log_mask_set: Added strbuf_strip_suffix() - Unchecked add_watch return: Now logs failure in rename_dir() - String building: Consolidated strbuf operations with strbuf_addf() - Translation markers: Added _() to all error_errno() messages Based on work from #1352 by Eric DeCosta, and #1667 by Marziyeh Esipreh, updated to work with the current codebase and address all review feedback. Signed-off-by: Paul Tarjan <github@paulisageek.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Goal is to deliver fsmonitor for Linux that is on par with fsmonitor for Windows and Mac OS.
This patch set builds upon previous work for done for Windows and Mac OS to implement a fsmonitor back-end for Linux based on the Linux inotify API. inotify differs significantly from the equivalent Windows and Mac OS APIs in that a watch must be registered for every directory of interest (rather than a singular watch at the root of the directory tree) and special care must be taken to handle directory renames correctly.
More information about inotify: https://man7.org/linux/man-pages/man7/inotify.7.html
v6 differs from v5:
v5 differs from v4:
v4 differs from v3:
v3 differs from v2:
v2 differs from v1:
v1 differs from v0:
cc: Eric Sunshine sunshine@sunshineco.com
cc: Ævar Arnfjörð Bjarmason avarab@gmail.com
cc: Glen Choo chooglen@google.com
cc: Johannes Schindelin Johannes.Schindelin@gmx.de
cc: Taylor Blau me@ttaylorr.com