Comparing version 0.1.2 to 1.0.0
229
index.js
@@ -0,142 +1,123 @@ | ||
var EventEmitter = require('events').EventEmitter; | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var Seq = require('seq'); | ||
function createInodeChecker() { | ||
var inodes = {}; | ||
return function inodeSeen(inode) { | ||
if (inodes[inode]) { | ||
return true; | ||
} else { | ||
inodes[inode] = true; | ||
return false; | ||
} | ||
module.exports = function walk (dir, opts, emitter, dstat) { | ||
if (!opts) opts = {}; | ||
var fdir = opts._original || dir; | ||
opts._original = undefined; | ||
if (!emitter) { | ||
emitter = new EventEmitter; | ||
emitter._pending = 0; | ||
emitter._seen = {}; | ||
} | ||
} | ||
exports = module.exports = find; | ||
exports.find = find; | ||
function find (base, options, cb) { | ||
cb = arguments[arguments.length - 1]; | ||
if (typeof(cb) !== 'function') { | ||
cb = undefined; | ||
} | ||
var em = new EventEmitter; | ||
var inodeSeen = createInodeChecker(); | ||
emitter._pending ++; | ||
function finder (dir, f) { | ||
Seq() | ||
.seq(fs.readdir, dir, Seq) | ||
.flatten() | ||
.seqEach(function (file) { | ||
var p = dir + '/' + file; | ||
fs.lstat(p, this.into(p)); | ||
}) | ||
.seq(function () { | ||
this(null, Object.keys(this.vars)); | ||
}) | ||
.flatten() | ||
.seqEach(function (file) { | ||
var stat = this.vars[file]; | ||
if (cb) cb(file, stat); | ||
if (inodeSeen(stat.ino)) { | ||
// already seen this inode, probably a recursive symlink | ||
this(null); | ||
} | ||
else { | ||
em.emit('path', file, stat); | ||
if (stat.isSymbolicLink()) { | ||
em.emit('link', file, stat); | ||
if (options && options.follow_symlinks) { | ||
path.exists(file, function(exists) { | ||
if (exists) { | ||
fs.readlink(file, function(err, resolvedPath) { | ||
if (err) { | ||
em.emit('error', err); | ||
} else { | ||
finder(path.resolve(path.dir(file), resolvedPath)); | ||
} | ||
}); | ||
} | ||
}); | ||
} else { | ||
this(null); | ||
} | ||
} | ||
else if (stat.isDirectory()) { | ||
em.emit('directory', file, stat); | ||
finder(file, this); | ||
} | ||
else { | ||
em.emit('file', file, stat); | ||
this(null); | ||
} | ||
} | ||
}) | ||
.seq(f.bind({}, null)) | ||
.catch(em.emit.bind(em, 'error')) | ||
; | ||
if (dstat) { | ||
var stopped = false; | ||
emitter.emit('directory', fdir, dstat, function stop () { | ||
stopped = true; | ||
}); | ||
emitter.emit('path', fdir, dstat); | ||
if (!stopped) fs.readdir(dir, onreaddir); | ||
else check() | ||
} | ||
fs.lstat(base, function (err, s) { | ||
if (err) { | ||
em.emit('error', err); | ||
else fs.lstat(dir, function onstat (err, stat) { | ||
if (err) return finish(); | ||
emitter._seen[stat.ino] = true; | ||
if (stat.isSymbolicLink() && opts.followSymlinks) { | ||
emitter.emit('link', fdir, stat); | ||
fs.readlink(dir, function (err, rfile) { | ||
if (err) return finish(); | ||
var file_ = path.resolve(dir, rfile); | ||
emitter.emit('readlink', fdir, file_); | ||
fs.lstat(file_, onstat); | ||
}); | ||
} | ||
if (s.isDirectory()) { | ||
finder(base, em.emit.bind(em, 'end')); | ||
else if (stat.isSymbolicLink()) { | ||
emitter.emit('link', fdir, stat); | ||
emitter.emit('path', fdir, stat); | ||
finish(); | ||
} | ||
else if (s.isSymbolicLink()) { | ||
if (cb) cb(base, s); | ||
em.emit('link', base, s); | ||
em.emit('end'); | ||
else if (stat.isDirectory()) { | ||
var stopped = false; | ||
emitter.emit('directory', fdir, stat, function stop () { | ||
stopped = true; | ||
}); | ||
emitter.emit('path', fdir, stat); | ||
if (!stopped) fs.readdir(dir, onreaddir); | ||
else check() | ||
} | ||
else { | ||
if (cb) cb(base, s); | ||
em.emit('file', base, s); | ||
em.emit('end'); | ||
emitter.emit('file', fdir, stat); | ||
emitter.emit('path', fdir, stat); | ||
finish(); | ||
} | ||
}); | ||
return em; | ||
}; | ||
exports.findSync = function findSync(dir, options, callback) { | ||
cb = arguments[arguments.length - 1]; | ||
if (typeof(cb) !== 'function') { | ||
cb = undefined; | ||
return emitter; | ||
function check () { | ||
if (-- emitter._pending === 0) finish(); | ||
} | ||
var inodeSeen = createInodeChecker(); | ||
var files = []; | ||
var fileQueue = []; | ||
var processFile = function processFile(file) { | ||
var stat = fs.lstatSync(file); | ||
if (inodeSeen(stat.ino)) { | ||
return; | ||
} | ||
files.push(file); | ||
cb && cb(file, stat) | ||
function finish () { | ||
emitter.emit('end'); | ||
emitter._seen = null; | ||
} | ||
function onreaddir (err, files) { | ||
emitter._pending --; | ||
if (err) return check(); | ||
files.forEach(function (rfile) { | ||
emitter._pending ++; | ||
var file = path.join(fdir, rfile); | ||
fs.lstat(file, function (err, stat) { | ||
if (err) check() | ||
else onstat(file, stat) | ||
}); | ||
}); | ||
} | ||
function onstat (file, stat, original) { | ||
if (emitter._seen[stat.ino]) return check(); | ||
emitter._seen[stat.ino] = true; | ||
if (stat.isDirectory()) { | ||
fs.readdirSync(file).forEach(function(f) { fileQueue.push(path.join(file, f)); }); | ||
} else if (stat.isSymbolicLink()) { | ||
if (options && options.follow_symlinks && path.existsSync(file)) { | ||
fileQueue.push(fs.realpathSync(file)); | ||
} | ||
if (original) opts._original = original; | ||
walk(file, opts, emitter, stat); | ||
check(); | ||
} | ||
}; | ||
/* we don't include the starting directory unless it is a file */ | ||
var stat = fs.lstatSync(dir); | ||
if (stat.isDirectory()) { | ||
fs.readdirSync(dir).forEach(function(f) { fileQueue.push(path.join(dir, f)); }); | ||
} else { | ||
fileQueue.push(dir); | ||
else if (stat.isSymbolicLink() && opts.followSymlinks) { | ||
emitter.emit('link', file, stat); | ||
fs.readlink(file, function (err, rfile) { | ||
if (err) return check(); | ||
var file_ = path.resolve(path.dirname(file), rfile); | ||
emitter.emit('readlink', file, file_); | ||
fs.lstat(file_, function (err, stat_) { | ||
if (err) return check(); | ||
emitter._pending ++; | ||
onstat(file_, stat_, file); | ||
check(); | ||
}); | ||
}); | ||
} | ||
else if (stat.isSymbolicLink()) { | ||
emitter.emit('link', file, stat); | ||
emitter.emit('path', file, stat); | ||
check(); | ||
} | ||
else { | ||
emitter.emit('file', file, stat); | ||
emitter.emit('path', file, stat); | ||
check(); | ||
} | ||
} | ||
while (fileQueue.length > 0) { | ||
processFile(fileQueue.shift()); | ||
} | ||
return files; | ||
}; | ||
exports.find.sync = exports.findSync; |
{ | ||
"name" : "findit", | ||
"version" : "0.1.2", | ||
"description" : "Walk a directory tree.", | ||
"main" : "./index.js", | ||
"dependencies" : { | ||
"seq" : ">=0.1.7" | ||
}, | ||
"devDependencies" : { | ||
"hashish" : ">=0.0.2 <0.1", | ||
"expresso" : "0.7.x" | ||
}, | ||
"scripts" : { | ||
"test" : "expresso" | ||
}, | ||
"repository" : { | ||
"type" : "git", | ||
"url" : "http://github.com/substack/node-findit.git" | ||
}, | ||
"keywords" : [ | ||
"find", | ||
"walk", | ||
"directory", | ||
"recursive", | ||
"tree" | ||
], | ||
"author" : { | ||
"name" : "James Halliday", | ||
"email" : "mail@substack.net", | ||
"url" : "http://substack.net" | ||
}, | ||
"license" : "MIT/X11", | ||
"engine" : ["node >=0.2.0"] | ||
"name": "findit", | ||
"version": "1.0.0", | ||
"description": "walk a directory tree recursively with events", | ||
"main": "index.js", | ||
"devDependencies": { | ||
"tap": "~0.4.4" | ||
}, | ||
"scripts": { | ||
"test": "tap test/*.js" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "http://github.com/substack/node-findit.git" | ||
}, | ||
"keywords": [ | ||
"find", | ||
"walk", | ||
"directory", | ||
"recursive", | ||
"tree", | ||
"traversal" | ||
], | ||
"author": { | ||
"name": "James Halliday", | ||
"email": "mail@substack.net", | ||
"url": "http://substack.net" | ||
}, | ||
"license": "MIT" | ||
} |
@@ -1,18 +0,12 @@ | ||
var assert = require('assert'); | ||
var find = require('../').find; | ||
var findSync = require('../').findSync; | ||
var find = require('../'); | ||
var test = require('tap').test; | ||
exports.foo = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('Never caught "end"'); | ||
}, 5000); | ||
test('foo', function (t) { | ||
var finder = find(__dirname + '/foo'); | ||
var ps = {}; | ||
var finder = find(__dirname + '/foo', function (file, stat) { | ||
ps[file] = stat.isDirectory(); | ||
}); | ||
var paths = [] | ||
finder.on('path', function (p) { | ||
finder.on('path', function (p, stat) { | ||
paths.push(p); | ||
ps[p] = stat.isDirectory(); | ||
}); | ||
@@ -31,4 +25,4 @@ | ||
finder.on('end', function () { | ||
clearTimeout(to); | ||
var ref = { | ||
'' : true, | ||
'a' : true, | ||
@@ -43,14 +37,14 @@ 'a/b' : true, | ||
assert.eql(Object.keys(ref).length, Object.keys(ps).length); | ||
t.equal(Object.keys(ref).length, Object.keys(ps).length); | ||
var count = { dirs : 0, files : 0, paths : 0 }; | ||
Object.keys(ref).forEach(function (key) { | ||
var file = __dirname + '/foo/' + key; | ||
assert.eql(ref[key], ps[file]); | ||
var file = (__dirname + '/foo/' + key).replace(/\/$/, ''); | ||
t.equal(ref[key], ps[file]); | ||
if (ref[key]) { | ||
assert.ok(dirs.indexOf(file) >= 0); | ||
t.ok(dirs.indexOf(file) >= 0); | ||
count.dirs ++; | ||
} | ||
else { | ||
assert.ok(files.indexOf(file) >= 0); | ||
t.ok(files.indexOf(file) >= 0); | ||
count.files ++; | ||
@@ -60,23 +54,7 @@ } | ||
assert.eql(count.dirs, dirs.length); | ||
assert.eql(count.files, files.length); | ||
assert.eql(paths.sort(), Object.keys(ps).sort()); | ||
t.deepEqual(count.dirs, dirs.length); | ||
t.deepEqual(count.files, files.length); | ||
t.deepEqual(paths.sort(), Object.keys(ps).sort()); | ||
t.end(); | ||
}); | ||
}; | ||
exports.fooSync = function () { | ||
assert.eql( | ||
findSync(__dirname + '/foo') | ||
.reduce(function (files, file) { | ||
files[file] = true; | ||
return files; | ||
}, {}), | ||
[ 'a', 'a/b', 'a/b/c', 'x', 'a/y', 'a/b/z', 'a/b/c/w' ] | ||
.reduce(function (files, file) { | ||
files[__dirname + '/foo/' + file] = true; | ||
return files; | ||
}, {}) | ||
); | ||
assert.eql(findSync(__dirname + '/foo/x'), [ __dirname + '/foo/x' ]); | ||
}; | ||
}); |
@@ -1,13 +0,6 @@ | ||
var assert = require('assert'); | ||
var find = require('../'); | ||
var test = require('tap').test; | ||
exports.module = function () { | ||
assert.eql(find.findSync, find.find.sync); | ||
assert.eql(find, find.find); | ||
}; | ||
exports.file = function () { | ||
var to = setTimeout(function () { | ||
assert.fail('never ended'); | ||
}, 5000); | ||
test('single file', function (t) { | ||
t.plan(2); | ||
@@ -17,3 +10,3 @@ var finder = find(__filename); | ||
finder.on('file', function (file) { | ||
assert.equal(file, __filename); | ||
t.equal(file, __filename); | ||
files.push(file); | ||
@@ -23,9 +16,8 @@ }); | ||
finder.on('directory', function (dir) { | ||
assert.fail(dir); | ||
t.fail(dir); | ||
}); | ||
finder.on('end', function () { | ||
clearTimeout(to); | ||
assert.deepEqual(files, [ __filename ]); | ||
t.deepEqual(files, [ __filename ]); | ||
}); | ||
}; | ||
}); |
@@ -1,42 +0,36 @@ | ||
var assert = require('assert'); | ||
var test = require('tap').test; | ||
var path = require('path'); | ||
var findit = require('../'); | ||
var to = setTimeout(function () { | ||
assert.fail('never ended'); | ||
}, 5000); | ||
function find_helper(dir, options, callback) { | ||
function helper(t, dir, options, callback) { | ||
var symlinks = []; | ||
var files = []; | ||
var dirs = []; | ||
var finder = findit.find(dir, options); | ||
var finder = findit(dir, options); | ||
finder.on('link', function (link, stat) { | ||
assert.ok(stat.isSymbolicLink()); | ||
t.ok(stat.isSymbolicLink()); | ||
symlinks.push(path.basename(link)); | ||
}); | ||
finder.on('file', function (file, stat) { | ||
assert.ok(stat.isFile()); | ||
t.ok(stat.isFile()); | ||
files.push(path.basename(file)); | ||
}); | ||
finder.on('directory', function (dir, stat) { | ||
assert.ok(stat.isDirectory()); | ||
t.ok(stat.isDirectory()); | ||
dirs.push(path.basename(dir)); | ||
}); | ||
finder.on('error', function (err) { | ||
assert.fail(err); | ||
t.fail(err); | ||
}); | ||
finder.on('end', function () { | ||
clearTimeout(to); | ||
symlinks.sort(); | ||
files.sort(); | ||
dirs.sort(); | ||
callback({ symlinks: symlinks, files: files, dirs: dirs }); | ||
@@ -46,29 +40,40 @@ }); | ||
exports.links = function() { | ||
find_helper(__dirname + '/symlinks/dir1', { follow_symlinks: false }, function(data) { | ||
assert.eql(['dangling-symlink', 'link-to-dir2', 'link-to-file'], data.symlinks); | ||
assert.eql(['file1'], data.files); | ||
assert.eql([], data.dirs); | ||
}); | ||
}; | ||
test('links', function (t) { | ||
helper(t, __dirname + '/symlinks/dir1', { followSymlinks: false }, done); | ||
function done (data) { | ||
t.deepEqual(data.symlinks, [ | ||
'dangling-symlink', 'link-to-dir2', 'link-to-file' | ||
]); | ||
t.deepEqual(data.files, [ 'file1' ]); | ||
t.deepEqual(data.dirs, [ 'dir1' ]); | ||
t.end(); | ||
} | ||
}); | ||
exports.follow_links = function() { | ||
find_helper(__dirname + '/symlinks/dir1', { follow_symlinks: true }, function(data) { | ||
assert.eql(['cyclic-link-to-dir1', 'dangling-symlink', 'link-to-dir2', 'link-to-file'], data.symlinks); | ||
assert.eql(['file', 'file1', 'file2'], data.files); | ||
assert.eql(['dir1', 'dir2'], data.dirs); | ||
}); | ||
}; | ||
test('follow links', function (t) { | ||
helper(t, __dirname + '/symlinks/dir1', { followSymlinks: true }, done); | ||
function done (data) { | ||
t.deepEqual(data.symlinks, [ | ||
'cyclic-link-to-dir1', 'dangling-symlink', 'link-to-dir2', | ||
'link-to-file' | ||
]); | ||
t.deepEqual(data.files, ['file', 'file1', 'file2']); | ||
t.deepEqual(data.dirs, [ 'dir1', 'link-to-dir2' ]); | ||
t.end(); | ||
} | ||
}); | ||
exports.links_sync = function() { | ||
var files = findit.findSync(__dirname + '/symlinks/dir1', { follow_symlinks: false }).map(path.basename); | ||
files.sort(); | ||
assert.eql(['dangling-symlink', 'file1', 'link-to-dir2', 'link-to-file'], files); | ||
}; | ||
exports.follow_links_sync = function() { | ||
var files = findit.findSync(__dirname + '/symlinks/dir1', { follow_symlinks: true }).map(path.basename); | ||
files.sort(); | ||
assert.eql(['cyclic-link-to-dir1', 'dangling-symlink', 'dir1', 'dir2', 'file', 'file1', 'file2', 'link-to-dir2', 'link-to-file'], files); | ||
}; | ||
test('parent links', function (t) { | ||
helper(t, __dirname + '/symlinks', { followSymlinks: true }, done); | ||
function done (data) { | ||
t.deepEqual(data.symlinks, [ | ||
'cyclic-link-to-dir1', 'dangling-symlink', 'link-to-dir2', | ||
'link-to-file' | ||
]); | ||
t.deepEqual(data.files, ['file', 'file1', 'file2']); | ||
t.deepEqual(data.dirs, [ 'dir1', 'dir2', 'symlinks' ]); | ||
t.end(); | ||
} | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
1
27
0
0
1
12527
278
85
- Removedseq@>=0.1.7
- Removedchainsaw@0.0.9(transitive)
- Removedhashish@0.0.4(transitive)
- Removedseq@0.3.5(transitive)
- Removedtraverse@0.3.9(transitive)