@@ -100,7 +100,7 @@ static void log_flags_set(const char *path, const FSEventStreamEventFlags flag)
if (flag & kFSEventStreamEventFlagItemCloned)
strbuf_addstr(&msg, "ItemCloned|");
- trace_printf_key(&trace_fsmonitor, "fsevent: '%s', flags=%u %s",
+ trace_printf_key(&trace_fsmonitor, "fsevent: '%s', flags=0x%x %s",
path, flag, msg.buf);
strbuf_release(&msg);
@@ -125,6 +125,31 @@ static int ef_is_dropped(const FSEventStreamEventFlags ef)
ef & kFSEventStreamEventFlagUserDropped);
}
+/*
+ * If an `xattr` change is the only reason we received this event,
+ * then silently ignore it. Git doesn't care about xattr's. We
+ * have to be careful here because the kernel can combine multiple
+ * events for a single path. And because events always have certain
+ * bits set, such as `ItemIsFile` or `ItemIsDir`.
+ *
+ * Return 1 if we should ignore it.
+ */
+static int ef_ignore_xattr(const FSEventStreamEventFlags ef)
+{
+ static const FSEventStreamEventFlags mask =
+ kFSEventStreamEventFlagItemChangeOwner |
+ kFSEventStreamEventFlagItemCreated |
+ kFSEventStreamEventFlagItemFinderInfoMod |
+ kFSEventStreamEventFlagItemInodeMetaMod |
+ kFSEventStreamEventFlagItemModified |
+ kFSEventStreamEventFlagItemRemoved |
+ kFSEventStreamEventFlagItemRenamed |
+ kFSEventStreamEventFlagItemXattrMod |
+ kFSEventStreamEventFlagItemCloned;
+
+ return ((ef & mask) == kFSEventStreamEventFlagItemXattrMod);
+}
+
static void fsevent_callback(ConstFSEventStreamRef streamRef,
void *ctx,
size_t num_of_events,
@@ -190,6 +215,13 @@ static void fsevent_callback(ConstFSEventStreamRef streamRef,
continue;
}
+ if (ef_ignore_xattr(event_flags[k])) {
+ trace_printf_key(&trace_fsmonitor,
+ "ignore-xattr: '%s', flags=0x%x",
+ path_k, event_flags[k]);
+ continue;
+ }
+
switch (fsmonitor_classify_path_absolute(state, path_k)) {
case IS_INSIDE_DOT_GIT_WITH_COOKIE_PREFIX: