From 965c67601e4a6b2822e9d79ef307102a84fabe47 Mon Sep 17 00:00:00 2001 From: Yuan Chuan Date: Thu, 18 Apr 2019 10:39:40 +0800 Subject: [PATCH] Fix windows (#86) * Detect temporary editor files more wisely. Fix #85 * Avoid side effects whenever possible. Fix #79 --- .gitignore | 1 + README.md | 4 ---- lib/watch.js | 39 ++++++++++++++++++++++++++++++++------- test/test.js | 16 ++++++++++++++-- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index ce5deeb..4bf3a39 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ test/utils/__TREE__ .nyc_output/ coverage/ package-lock.json +.DS_Store diff --git a/README.md b/README.md index a9ebe4c..a8827d6 100644 --- a/README.md +++ b/README.md @@ -132,10 +132,6 @@ watcher.isClosed() ## Known issues -**Windows** - - * Will output its parent directory when a new file/directory is created in a deep directory. - **Windows, node < v4.2.5** * Failed to detect `remove` event diff --git a/lib/watch.js b/lib/watch.js index 5be51e2..8911959 100644 --- a/lib/watch.js +++ b/lib/watch.js @@ -55,17 +55,42 @@ function getMessages(cache) { // Saving file from an editor? If so, assuming the // non-existed files in the cache are temporary files // generated by an editor and thus be filtered. - var dup = hasDup(cache.map(function(c) { - return c.replace(/^[~#]+|[~#]+$/, ''); - })); + var reg = /~$|^\.#|^##$/g; + var hasSpecialChar = cache.some(function(c) { + return reg.test(c); + }); - if (dup) { - filtered = filtered.filter(function(m) { - return is.exists(m) + if (hasSpecialChar) { + var dup = hasDup(cache.map(function(c) { + return c.replace(reg, ''); + })); + if (dup) { + filtered = filtered.filter(function(m) { + return is.exists(m); + }); + } + } + + // Prevent redundant event for its parent when creating file/directory. + // The operation is kinda expensive so only be triggered under Windows. + // https://github.com/yuanchuan/node-watch/issues/79 + if (is.windows()) { + var parents = filtered.map(function(n) { + return path.parse(n).dir; + }); + filtered = filtered.filter(function(n) { + // Skip on removal + if (!is.exists(n)) { + return true; + } + // Ignore the parent directory + return !parents.some(function(m) { + return is.samePath(n, m); + }); }); } - return composeMessage(filtered) + return composeMessage(filtered); } function debounce(info, fn) { diff --git a/test/test.js b/test/test.js index 58e5371..e29eaf8 100644 --- a/test/test.js +++ b/test/test.js @@ -237,6 +237,18 @@ describe('file events', function() { }); }); + it('should identify `remove` event on directory', function(done) { + var dir = 'home/a'; + var home = tree.getPath('home'); + var fpath = tree.getPath(dir); + watcher = watch(home, function(evt, name) { + if (evt === 'remove' && name === fpath) done(); + }); + watcher.on('ready', function() { + tree.remove(dir); + }); + }); + it('should identify `update` event', function(done) { var file = 'home/a/file1'; var fpath = tree.getPath(file); @@ -390,7 +402,7 @@ describe('options', function() { delay: 0, recursive: true, filter: function(name) { - return /bb\/file2/.test(name); + return /file2/.test(name); } } @@ -407,7 +419,7 @@ describe('options', function() { tree.modify(file2); setTimeout(function() { - assert.equal(times, 1, 'report file2'); + assert.equal(times, 1, 'should only report /home/bb/file2 once'); assert.equal(matchIgnoredFile, false, 'home/bb/file1 should be ignored'); done(); }, 100);