diff --git a/index.js b/index.js index cc3abdd..773b784 100644 --- a/index.js +++ b/index.js @@ -74,6 +74,17 @@ function walkdir() { if (dirent.isDirectory()) { queue.push(nextpath); + } else if (dirent.isSymbolicLink()) { + // If it's a symlink, check if the symlink points to a directory + fs.stat(nextpath, function (err, stats) { + if (err) { + return cb(err); + } + + if (stats.isDirectory()) { + queue.push(nextpath); + } + }); } } } diff --git a/test/fixtures/symlinks/file-a.txt b/test/fixtures/symlinks/file-a.txt new file mode 100644 index 0000000..4ef30bb --- /dev/null +++ b/test/fixtures/symlinks/file-a.txt @@ -0,0 +1 @@ +file a diff --git a/test/fixtures/symlinks/symlink-dest b/test/fixtures/symlinks/symlink-dest new file mode 120000 index 0000000..f2e2d0e --- /dev/null +++ b/test/fixtures/symlinks/symlink-dest @@ -0,0 +1 @@ +../whatsgoingon \ No newline at end of file diff --git a/test/index.js b/test/index.js index d3194e3..c87c057 100644 --- a/test/index.js +++ b/test/index.js @@ -334,6 +334,18 @@ function suite(moduleName) { base: dir + '/fixtures', path: dir + '/fixtures/stuff/test.dmc', }, + { + cwd: dir, + base: dir + '/fixtures', + path: dir + '/fixtures/symlinks/symlink-dest/test.js', + }, + { + cwd: dir, + base: dir + '/fixtures', + path: + dir + + '/fixtures/symlinks/symlink-dest/hey/isaidhey/whatsgoingon/test.txt', + }, ]; var globs = [ @@ -344,12 +356,14 @@ function suite(moduleName) { ]; function assert(pathObjs) { - expect(pathObjs.length).toEqual(5); + expect(pathObjs.length).toEqual(7); expect(pathObjs).toContainEqual(expected[0]); expect(pathObjs).toContainEqual(expected[1]); expect(pathObjs).toContainEqual(expected[2]); expect(pathObjs).toContainEqual(expected[3]); expect(pathObjs).toContainEqual(expected[4]); + expect(pathObjs).toContainEqual(expected[5]); + expect(pathObjs).toContainEqual(expected[6]); } stream.pipeline([globStream(globs, { cwd: dir }), concat(assert)], done); @@ -736,6 +750,37 @@ function suite(moduleName) { done ); }); + + it('traverses symlinked directories', function (done) { + var expected = [ + { + cwd: dir, + base: dir + '/fixtures/symlinks', + path: dir + '/fixtures/symlinks/file-a.txt', + }, + { + cwd: dir, + base: dir + '/fixtures/symlinks', + path: + dir + + '/fixtures/symlinks/symlink-dest/hey/isaidhey/whatsgoingon/test.txt', + }, + ]; + + function assert(pathObjs) { + expect(pathObjs.length).toBe(2); + expect(pathObjs).toContainEqual(expected[0]); + expect(pathObjs).toContainEqual(expected[1]); + } + + stream.pipeline( + [ + globStream(['./fixtures/symlinks/**/*.txt'], { cwd: dir }), + concat(assert), + ], + done + ); + }); }); describe('options', function () { @@ -1039,6 +1084,28 @@ function suite(moduleName) { stream.pipeline([gs, concat()], assert); }); + it('destroys the stream if walker errors when following symlink', function (done) { + var expectedError = new Error('Stubbed error'); + + var gs = globStream('./fixtures/**/*.dmc', { cwd: dir }); + + function stubError(dirpath, cb) { + cb(expectedError); + } + + var spy = sinon.spy(gs, 'destroy'); + sinon.stub(fs, 'stat').callsFake(stubError); + + function assert(err) { + sinon.restore(); + expect(spy.called).toEqual(true); + expect(err).toBe(expectedError); + done(); + } + + stream.pipeline([gs, concat()], assert); + }); + it('does not emit an error if stream is destroyed without an error', function (done) { var gs = globStream('./fixtures/**/*.dmc', { cwd: dir });