Fix inotify based directory watcher for recursive directory adds.

Newly added folders were not scanned recursively, which would result in sub folders that already exist or are added concurrently to not be watched.
This commit is contained in:
Sönke Ludwig 2017-12-02 02:54:13 +01:00 committed by Leonid Kramer
parent 29aee9ee52
commit 9ca1a4c3a6

View file

@ -42,20 +42,8 @@ final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriver
m_watches[ret] = WatchState(null, path, recursive); m_watches[ret] = WatchState(null, path, recursive);
addWatch(ret, path, ""); addWatch(ret, path, "");
if (recursive) { if (recursive)
try { addSubWatches(ret, path, "");
auto base_segements = path.pathSplitter.walkLength;
if (path.isDir) () @trusted {
foreach (de; path.dirEntries(SpanMode.depth))
if (de.isDir) {
auto subdir = de.name.pathSplitter.drop(base_segements).buildPath;
addWatch(ret, path, subdir);
}
} ();
} catch (Exception e) {
// TODO: decide if this should be ignored or if the error should be forwarded
}
}
m_loop.initFD(FD(handle), FDFlags.none); m_loop.initFD(FD(handle), FDFlags.none);
m_loop.registerFD(FD(handle), EventMask.read); m_loop.registerFD(FD(handle), EventMask.read);
@ -135,10 +123,14 @@ final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriver
} }
auto name = () @trusted { return ev.name.ptr[0 .. strlen(ev.name.ptr)]; } (); auto name = () @trusted { return ev.name.ptr[0 .. strlen(ev.name.ptr)]; } ();
auto subdir = w.watcherPaths[ev.wd]; auto subdir = w.watcherPaths[ev.wd];
if (w.recursive && ev.mask & (IN_CREATE|IN_MOVED_TO) && ev.mask & IN_ISDIR) { if (w.recursive && ev.mask & (IN_CREATE|IN_MOVED_TO) && ev.mask & IN_ISDIR) {
addWatch(id, w.basePath, subdir == "" ? name.idup : buildPath(subdir, name)); auto subpath = subdir == "" ? name.idup : buildPath(subdir, name);
addWatch(id, w.basePath, subpath);
if (w.recursive)
addSubWatches(id, w.basePath, subpath);
} }
ch.baseDirectory = m_watches[id].basePath; ch.baseDirectory = m_watches[id].basePath;
@ -153,6 +145,29 @@ final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriver
} }
} }
private bool addSubWatches(WatcherID handle, string base_path, string subpath)
{
import std.path : buildPath, pathSplitter;
import std.range : drop;
import std.range.primitives : walkLength;
try {
auto path = buildPath(base_path, subpath);
auto base_segements = base_path.pathSplitter.walkLength;
if (path.isDir) () @trusted {
foreach (de; path.dirEntries(SpanMode.depth))
if (de.isDir) {
auto subdir = de.name.pathSplitter.drop(base_segements).buildPath;
addWatch(handle, base_path, subdir);
}
} ();
return true;
} catch (Exception e) {
// TODO: decide if this should be ignored or if the error should be forwarded
return false;
}
}
private bool addWatch(WatcherID handle, string base_path, string path) private bool addWatch(WatcherID handle, string base_path, string path)
{ {
import std.path : buildPath; import std.path : buildPath;