From 9120982bed86c53c80c35400a35fa0916f50e7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Wed, 27 May 2020 17:56:28 +0200 Subject: [PATCH 1/3] Fix watching symlinked paths with FSEvents. The events reported always use the canonical path, which broke the relative path logic. TO counter this, the canonical path is now determined explicitly. --- source/eventcore/drivers/posix/watchers.d | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/source/eventcore/drivers/posix/watchers.d b/source/eventcore/drivers/posix/watchers.d index d2fd2a0..ba9de14 100644 --- a/source/eventcore/drivers/posix/watchers.d +++ b/source/eventcore/drivers/posix/watchers.d @@ -228,14 +228,30 @@ final class FSEventsEventDriverWatchers(Events : EventDriverEvents) : EventDrive final override WatcherID watchDirectory(string path, bool recursive, FileChangesCallback on_change) @trusted { - import std.path : absolutePath; + import std.file : isSymlink, readLink; + import std.path : absolutePath, buildPath, buildNormalizedPath, dirName, pathSplitter; FSEventStreamContext ctx; ctx.info = () @trusted { return cast(void*)this; } (); + static string resolveSymlinks(string path) + { + string res; + foreach (ps; path.pathSplitter) { + if (!res.length) res = ps; + else res = buildPath(res, ps); + if (isSymlink(res)) { + res = readLink(res).absolutePath(dirName(res)); + } + } + return res.buildNormalizedPath; + } + string abspath; - try abspath = absolutePath(path); - catch (Exception e) assert(false, e.msg); + try abspath = resolveSymlinks(absolutePath(path)); + catch (Exception e) { + return WatcherID.invalid; + } if (m_handleCounter == 0) { m_handleCounter++; From 8695b4d32c63e2f986e52528d8384c932411a41e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Wed, 27 May 2020 17:57:27 +0200 Subject: [PATCH 2/3] Ignore sentinel events for the FSEvents watcher. This caused the watcher to be endlessly recreated in rapid succession. --- source/eventcore/drivers/posix/watchers.d | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/eventcore/drivers/posix/watchers.d b/source/eventcore/drivers/posix/watchers.d index ba9de14..5bedf24 100644 --- a/source/eventcore/drivers/posix/watchers.d +++ b/source/eventcore/drivers/posix/watchers.d @@ -338,6 +338,13 @@ final class FSEventsEventDriverWatchers(Events : EventDriverEvents) : EventDrive auto flagsarr = () @trusted { return eventFlags[0 .. numEvents]; } (); auto idarr = () @trusted { return eventIds[0 .. numEvents]; } (); + if (flagsarr[0] & kFSEventStreamEventFlagHistoryDone) { + if (!--numEvents) return; + patharr = patharr[1 .. $]; + flagsarr = flagsarr[1 .. $]; + idarr = idarr[1 .. $]; + } + // A new stream needs to be created after every change, because events // get coalesced per file (event flags get or'ed together) and it becomes // impossible to determine the actual event From eb9c49a57760a31589b2d5b17e43098f829a457b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Wed, 27 May 2020 17:58:28 +0200 Subject: [PATCH 3/3] Fix the FSEvent rename logic. It turned out to be impossible to determine the source and target names for a rename operation, so the actual existence of the file has to be used. --- source/eventcore/drivers/posix/watchers.d | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/eventcore/drivers/posix/watchers.d b/source/eventcore/drivers/posix/watchers.d index 5bedf24..b85fb8d 100644 --- a/source/eventcore/drivers/posix/watchers.d +++ b/source/eventcore/drivers/posix/watchers.d @@ -382,8 +382,7 @@ final class FSEventsEventDriverWatchers(Events : EventDriverEvents) : EventDrive // complex flags system to the three event types provided by // eventcore if (f & kFSEventStreamEventFlagItemRenamed) { - if (f & kFSEventStreamEventFlagItemCreated) - emit(FileChangeKind.removed); + if (!does_exist) emit(FileChangeKind.removed); else emit(FileChangeKind.added); } else if (f & kFSEventStreamEventFlagItemRemoved && !does_exist) { emit(FileChangeKind.removed);