From f0facd2e6803b926a5c1d52edb41174fcfe7f3db Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Sun, 31 Aug 2014 01:37:26 -0700 Subject: [PATCH] resolves #1223: fix interaction with symbolic links - symbolic links are followed if they are not broken - move `lookupFiles()` into `utils` module - add some tests for the symbolic link stuff - build --- bin/_mocha | 38 +------------------------------ lib/utils.js | 49 ++++++++++++++++++++++++++++++++++++++++ mocha.js | 49 ++++++++++++++++++++++++++++++++++++++++ test/acceptance/utils.js | 26 +++++++++++++++++++++ 4 files changed, 125 insertions(+), 37 deletions(-) diff --git a/bin/_mocha b/bin/_mocha index 7c39c6ceba..e4c25e8350 100755 --- a/bin/_mocha +++ b/bin/_mocha @@ -284,8 +284,6 @@ program.compilers.forEach(function(c) { extensions.push(ext); }); -var re = new RegExp('\\.(' + extensions.join('|') + ')$'); - // requires requires.forEach(function(mod) { @@ -302,7 +300,7 @@ var files = [] if (!args.length) args.push('test'); args.forEach(function(arg){ - files = files.concat(lookupFiles(arg, program.recursive)); + files = files.concat(utils.lookupFiles(arg, extensions, program.recursive)); }); // resolve @@ -439,40 +437,6 @@ function stop() { clearInterval(play.timer); } -/** - * Lookup file names at the given `path`. - */ - -function lookupFiles(path, recursive) { - var files = []; - - if (!exists(path)) { - if (exists(path + '.js')) { - path += '.js' - } else { - files = glob.sync(path); - if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'"); - return files; - } - } - - var stat = fs.statSync(path); - if (stat.isFile()) return path; - - fs.readdirSync(path).forEach(function(file){ - file = join(path, file); - var stat = fs.statSync(file); - if (stat.isDirectory()) { - if (recursive) files = files.concat(lookupFiles(file, recursive)); - return - } - if (!stat.isFile() || !re.test(file) || basename(file)[0] == '.') return; - files.push(file); - }); - - return files; -} - /** * Play the given array of strings. */ diff --git a/lib/utils.js b/lib/utils.js index aa39a7bd0f..77682443e9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -4,6 +4,9 @@ var fs = require('fs') , path = require('path') + , basename = path.basename + , exists = fs.existsSync || path.existsSync + , glob = require('glob') , join = path.join , debug = require('debug')('mocha:watch'); @@ -348,3 +351,49 @@ exports.canonicalize = function(obj, stack) { return canonicalizedObj; } + +/** + * Lookup file names at the given `path`. + */ +exports.lookupFiles = function lookupFiles(path, extensions, recursive) { + var files = []; + var re = new RegExp('\\.(' + extensions.join('|') + ')$'); + + if (!exists(path)) { + if (exists(path + '.js')) { + path += '.js'; + } else { + files = glob.sync(path); + if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'"); + return files; + } + } + + try { + var stat = fs.statSync(path); + if (stat.isFile()) return path; + } + catch (ignored) { + return; + } + + fs.readdirSync(path).forEach(function(file){ + file = join(path, file); + try { + var stat = fs.statSync(file); + if (stat.isDirectory()) { + if (recursive) { + files = files.concat(lookupFiles(file, recursive)); + } + return; + } + } + catch (ignored) { + return; + } + if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return; + files.push(file); + }); + + return files; +} diff --git a/mocha.js b/mocha.js index 2135a9554a..538537fbb7 100644 --- a/mocha.js +++ b/mocha.js @@ -5498,6 +5498,9 @@ require.register("utils.js", function(module, exports, require){ var fs = require('browser/fs') , path = require('browser/path') + , basename = path.basename + , exists = fs.existsSync || path.existsSync + , glob = require('glob') , join = path.join , debug = require('browser/debug')('mocha:watch'); @@ -5843,6 +5846,52 @@ exports.canonicalize = function(obj, stack) { return canonicalizedObj; } +/** + * Lookup file names at the given `path`. + */ +exports.lookupFiles = function lookupFiles(path, extensions, recursive) { + var files = []; + var re = new RegExp('\\.(' + extensions.join('|') + ')$'); + + if (!exists(path)) { + if (exists(path + '.js')) { + path += '.js'; + } else { + files = glob.sync(path); + if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'"); + return files; + } + } + + try { + var stat = fs.statSync(path); + if (stat.isFile()) return path; + } + catch (ignored) { + return; + } + + fs.readdirSync(path).forEach(function(file){ + file = join(path, file); + try { + var stat = fs.statSync(file); + if (stat.isDirectory()) { + if (recursive) { + files = files.concat(lookupFiles(file, recursive)); + } + return; + } + } + catch (ignored) { + return; + } + if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return; + files.push(file); + }); + + return files; +} + }); // module: utils.js // The global object is "self" in Web Workers. var global = (function() { return this; })(); diff --git a/test/acceptance/utils.js b/test/acceptance/utils.js index 9c900a92dd..7c3b8d2a24 100644 --- a/test/acceptance/utils.js +++ b/test/acceptance/utils.js @@ -86,4 +86,30 @@ describe('lib/utils', function () { utils.stringify(travis).should.equal('{\n "name": "travis"\n "whoami": "[Circular]"\n}'); }); }); + + describe('lookupFiles', function () { + var fs = require('fs'); + + beforeEach(function () { + fs.writeFileSync('/tmp/mocha-utils.js', 'yippy skippy ying yang yow'); + fs.symlinkSync('/tmp/mocha-utils.js', '/tmp/mocha-utils-link.js'); + }); + + it('should not choke on symlinks', function () { + utils.lookupFiles('/tmp', ['js'], false).should.eql(['/tmp/mocha-utils-link.js', '/tmp/mocha-utils.js']); + fs.existsSync('/tmp/mocha-utils-link.js').should.be.true; + fs.rename('/tmp/mocha-utils.js', '/tmp/bob'); + fs.existsSync('/tmp/mocha-utils-link.js').should.be.true; + utils.lookupFiles('/tmp', ['js'], false).should.eql([]); + }); + + afterEach(function () { + ['/tmp/mocha-utils.js', '/tmp/mocha-utils-link.js', '/tmp/bob'].forEach(function (path) { + try { + fs.unlinkSync(path); + } + catch (ignored) {} + }); + }) + }); });