Skip to content

Instantly share code, notes, and snippets.

@carlos8f
Last active December 18, 2015 18:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlos8f/5824943 to your computer and use it in GitHub Desktop.
Save carlos8f/5824943 to your computer and use it in GitHub Desktop.
recursive readdir implementation
node_modules
test
{
"name": "rreaddir",
"version": "0.1.1",
"description": "recursive readdir",
"main": "readdir.js",
"scripts": {
"test": "tar -xf fixtures.tar.gz && ./node_modules/.bin/mocha test.js"
},
"repository": {
"type": "git",
"url": "https://gist.github.com/5824943.git"
},
"keywords": [
"recursive",
"readdir"
],
"author": "Carlos Rodriguez",
"license": "MIT",
"bugs": {
"url": "https://gist.github.com/5824943"
},
"homepage": "https://gist.github.com/5824943",
"devDependencies": {
"mocha": "^1.18.2",
"graceful-fs": "^2.0.3"
},
"dependencies": {
"debug": "^0.8.0"
}
}
var fs = require('fs')
, path = require('path')
// recursive readDir
module.exports = function readDir (startDir, options, cb) {
var debug = require('debug')('rreaddir');
if (typeof options === 'function') {
cb = options;
options = {};
}
options || (options = {});
var ret = []
, latch = 0
, errored = false
function addFile (file, stat) {
if (options.mark && stat.isDirectory()) file += path.sep;
if (options.stat) {
ret.push({
path: file,
stat: stat
});
}
else {
ret.push(file);
}
}
function onErr (err) {
if (errored) return;
if (err && err.code === 'ENOENT' && !options.strict) {
// file was probably deleted before we could stat it.
if (!--latch) cb(null, ret);
return;
}
errored = true;
cb(err);
}
(function read (dir) {
latch++;
debug('read', dir, latch);
(options.fs || fs).readdir(dir, function (err, files) {
if (err) return onErr(err);
latch += files.length;
debug('files', files.length, latch);
if (!--latch) cb(null, ret);
files.forEach(function (file) {
file = path.join(dir, file);
debug('file', file);
(options.fs || fs).stat(file, function (err, stat) {
debug('err', err);
if (err) return onErr(err);
if (stat.isDirectory()) {
debug('is a dir', file);
addFile(file, stat);
read(file);
}
else {
debug('is a file', file);
addFile(file, stat);
}
if (!--latch) {
debug('done');
cb(null, ret);
}
});
});
});
})(startDir);
};
var assert = require('assert')
, path = require('path')
describe('readDir', function () {
var readDir = require('./');
it('reads all files and dirs (relative)', function (done) {
readDir('./test/fixtures', function (err, files) {
assert.ifError(err);
assert.deepEqual(files.sort(), [
'test/fixtures/jesus',
'test/fixtures/totally',
'test/fixtures/totally/off',
'test/fixtures/totally/satan',
'test/fixtures/totally/the',
'test/fixtures/totally/the/hook',
'test/fixtures/whoa'
]);
done();
});
});
it('mark option', function (done) {
readDir('./test/fixtures', {mark: true}, function (err, files) {
assert.ifError(err);
assert.deepEqual(files.sort(), [
'test/fixtures/jesus',
'test/fixtures/totally/',
'test/fixtures/totally/off',
'test/fixtures/totally/satan',
'test/fixtures/totally/the/',
'test/fixtures/totally/the/hook',
'test/fixtures/whoa'
]);
done();
});
});
it('reads all files and dirs (absolute)', function (done) {
var base = path.join(__dirname, 'test', 'fixtures');
readDir(base, function (err, files) {
assert.ifError(err);
assert.deepEqual(files.sort(), [
base + '/jesus',
base + '/totally',
base + '/totally/off',
base + '/totally/satan',
base + '/totally/the',
base + '/totally/the/hook',
base + '/whoa'
]);
done();
});
});
it('stat option', function (done) {
readDir('./test/fixtures', {stat: true}, function (err, files) {
assert.ifError(err);
assert.equal(files.length, 7);
var paths = files.map(function (file) {
assert(file.stat);
assert(file.stat.mtime);
return file.path;
});
assert.deepEqual(paths.sort(), [
'test/fixtures/jesus',
'test/fixtures/totally',
'test/fixtures/totally/off',
'test/fixtures/totally/satan',
'test/fixtures/totally/the',
'test/fixtures/totally/the/hook',
'test/fixtures/whoa'
]);
done();
});
});
});
describe('readDir (custom fs)', function () {
var readDir = require('./');
var fs = require('graceful-fs');
it('reads all files and dirs (relative)', function (done) {
readDir('./test/fixtures', {fs: fs}, function (err, files) {
assert.ifError(err);
assert.deepEqual(files.sort(), [
'test/fixtures/jesus',
'test/fixtures/totally',
'test/fixtures/totally/off',
'test/fixtures/totally/satan',
'test/fixtures/totally/the',
'test/fixtures/totally/the/hook',
'test/fixtures/whoa'
]);
done();
});
});
it('mark option', function (done) {
readDir('./test/fixtures', {mark: true, fs: fs}, function (err, files) {
assert.ifError(err);
assert.deepEqual(files.sort(), [
'test/fixtures/jesus',
'test/fixtures/totally/',
'test/fixtures/totally/off',
'test/fixtures/totally/satan',
'test/fixtures/totally/the/',
'test/fixtures/totally/the/hook',
'test/fixtures/whoa'
]);
done();
});
});
it('reads all files and dirs (absolute)', function (done) {
var base = path.join(__dirname, 'test', 'fixtures');
readDir(base, {fs: fs}, function (err, files) {
assert.ifError(err);
assert.deepEqual(files.sort(), [
base + '/jesus',
base + '/totally',
base + '/totally/off',
base + '/totally/satan',
base + '/totally/the',
base + '/totally/the/hook',
base + '/whoa'
]);
done();
});
});
it('stat option', function (done) {
readDir('./test/fixtures', {fs: fs, stat: true}, function (err, files) {
assert.ifError(err);
assert.equal(files.length, 7);
var paths = files.map(function (file) {
assert(file.stat);
assert(file.stat.mtime);
return file.path;
});
assert.deepEqual(paths.sort(), [
'test/fixtures/jesus',
'test/fixtures/totally',
'test/fixtures/totally/off',
'test/fixtures/totally/satan',
'test/fixtures/totally/the',
'test/fixtures/totally/the/hook',
'test/fixtures/whoa'
]);
done();
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment