From e47870904a05c93cb8ad5caee983a86169336c05 Mon Sep 17 00:00:00 2001 From: Sergey Kruk Date: Mon, 3 Apr 2017 20:29:49 +0300 Subject: [PATCH] Fixing issue with broken symlinks Problem: When traversing a directory containig broken symbolic links, said links throw error before we have a chance to ignore them, which we might want to. Solution: When encountering error code `ENOENT` make `lstat` call which doesn't fail on broken links due to not following them. It is up to the user then to check if he needs to ignore this particular link via ignore function or pattern. Fixes #42 --- index.js | 17 +++++++++++++++++ test/recursive-readdir-test.js | 16 ++++++++++++++++ test/testbrokensymlink/brokenlink | 1 + test/testbrokensymlink/foo.bar | 0 4 files changed, 34 insertions(+) create mode 120000 test/testbrokensymlink/brokenlink create mode 100644 test/testbrokensymlink/foo.bar diff --git a/index.js b/index.js index 187440f..c971433 100644 --- a/index.js +++ b/index.js @@ -41,6 +41,23 @@ function readdir(path, ignores, callback) { var filePath = p.join(path, file) fs.stat(filePath, function(_err, stats) { if (_err) { + if (_err.code == 'ENOENT') { + fs.lstat(filePath, function(_lserr, stats) { + if (_lserr) { + return callback(_lserr) + } + + if (ignores.some(function(matcher) { return matcher(filePath, stats) })) { + pending -= 1 + if (!pending) { + return callback(null, list) + } + return null + } + return callback(_err) + }) + return null + } return callback(_err) } diff --git a/test/recursive-readdir-test.js b/test/recursive-readdir-test.js index 3cd85c5..80c2557 100644 --- a/test/recursive-readdir-test.js +++ b/test/recursive-readdir-test.js @@ -240,6 +240,22 @@ describe('readdir', function() { done() }) }) + + it('does not fail on broken symlink if it is ignored', function(done) { + var expectedFiles = getAbsolutePaths([ + '/testbrokensymlink/foo.bar' + ]) + function ignoreFunction(path, stats) { + return stats.isSymbolicLink(); + } + + readdir(p.join(__dirname, 'testbrokensymlink'), [ignoreFunction], function(err, list) { + assert.ifError(err) + assert.deepEqual(list.sort(), expectedFiles, + 'Failed to find expected files.') + done() + }) + }) }) it('works when there are no files to report except ignored files', function(done) { diff --git a/test/testbrokensymlink/brokenlink b/test/testbrokensymlink/brokenlink new file mode 120000 index 0000000..3f2a6ca --- /dev/null +++ b/test/testbrokensymlink/brokenlink @@ -0,0 +1 @@ +badlink \ No newline at end of file diff --git a/test/testbrokensymlink/foo.bar b/test/testbrokensymlink/foo.bar new file mode 100644 index 0000000..e69de29