Skip to content

Commit ef86439

Browse files
committed
Fixed for polling servers
It should now be able to watch symlinks that lead to outside of the watched folder when polling
1 parent c54bf67 commit ef86439

File tree

1 file changed

+47
-24
lines changed

1 file changed

+47
-24
lines changed

lib/DirectoryWatcher.js

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class DirectoryWatcher extends EventEmitter {
6161
this.watcherManager = watcherManager;
6262
this.options = options;
6363
this.path = directoryPath;
64+
this.watchingSymlink = false;
6465
// safeTime is the point in time after which reading is safe to be unchanged
6566
// timestamp is a value that should be compared with another timestamp (mtime)
6667
/** @type {Map<string, { safeTime: number, timestamp: number }} */
@@ -111,8 +112,8 @@ class DirectoryWatcher extends EventEmitter {
111112
this.watchInParentDirectory();
112113
}
113114
this.watcher = watchEventSource.watch(this.path);
114-
this.watcher.on("change", this.onWatchEvent.bind(this));
115115
this.watcher.on("error", this.onWatcherError.bind(this));
116+
this.watcher.on("change", this.onWatchEvent.bind(this));
116117
}
117118
} catch (err) {
118119
this.onWatcherError(err);
@@ -550,7 +551,9 @@ class DirectoryWatcher extends EventEmitter {
550551
fs.readdir(this.path, (err, items) => {
551552
if (this.closed) return;
552553
if (err) {
553-
if (err.code === "ENOENT" || err.code === "EPERM") {
554+
if (this.watchingSymlink && err.code == "ENOTDIR") {
555+
return;
556+
} else if (err.code === "ENOENT" || err.code === "EPERM") {
554557
this.onDirectoryRemoved("scan readdir failed");
555558
} else {
556559
this.onScanError(err);
@@ -627,22 +630,7 @@ class DirectoryWatcher extends EventEmitter {
627630
}
628631
});
629632
for (const itemPath of itemPaths) {
630-
const handleStats = (err2, stats) => {
631-
if (this.closed) return;
632-
if (err2) {
633-
if (
634-
err2.code === "ENOENT" ||
635-
err2.code === "EPERM" ||
636-
err2.code === "EACCES" ||
637-
err2.code === "EBUSY"
638-
) {
639-
this.setMissing(itemPath, initial, "scan (" + err2.code + ")");
640-
} else {
641-
this.onScanError(err2);
642-
}
643-
itemFinished();
644-
return;
645-
}
633+
const handleStats = (stats, symlinkStats) => {
646634
if (stats.isFile() || stats.isSymbolicLink()) {
647635
if (stats.mtime) {
648636
ensureFsAccuracy(stats.mtime);
@@ -654,7 +642,11 @@ class DirectoryWatcher extends EventEmitter {
654642
true,
655643
"scan (file)"
656644
);
657-
} else if (stats.isDirectory()) {
645+
}
646+
if (
647+
stats.isDirectory() ||
648+
(symlinkStats && symlinkStats.isDirectory())
649+
) {
658650
if (!initial || !this.directories.has(itemPath))
659651
this.setDirectory(
660652
itemPath,
@@ -665,11 +657,42 @@ class DirectoryWatcher extends EventEmitter {
665657
}
666658
itemFinished();
667659
};
668-
if (this.watcherManager.options.followSymlinks) {
669-
fs.stat(itemPath, handleStats);
670-
} else {
671-
fs.lstat(itemPath, handleStats);
672-
}
660+
fs.lstat(itemPath, (err2, stats) => {
661+
if (this.closed) return;
662+
if (err2) {
663+
if (
664+
err2.code === "ENOENT" ||
665+
err2.code === "EPERM" ||
666+
err2.code === "EACCES" ||
667+
err2.code === "EBUSY"
668+
) {
669+
this.setMissing(itemPath, initial, "scan (" + err2.code + ")");
670+
} else {
671+
this.onScanError(err2);
672+
}
673+
itemFinished();
674+
return;
675+
}
676+
if (
677+
stats.isSymbolicLink() &&
678+
this.watcherManager.options.followSymlinks
679+
) {
680+
fs.stat(itemPath, (err3, symlinkStats) => {
681+
if (this.closed) return;
682+
// something is wrong with the symlink, but not with the file itself
683+
if (err3) {
684+
handleStats(stats);
685+
this.watchingSymlink = false;
686+
return;
687+
}
688+
this.watchingSymlink = true;
689+
handleStats(stats, symlinkStats);
690+
});
691+
} else {
692+
this.watchingSymlink = false;
693+
handleStats(stats);
694+
}
695+
});
673696
}
674697
itemFinished();
675698
});

0 commit comments

Comments
 (0)