[Pkg-javascript-commits] [node-findit2] 01/02: Imported Upstream version 2.2.2
Andrew Kelley
andrewrk-guest at moszumanska.debian.org
Fri Oct 17 23:00:48 UTC 2014
This is an automated email from the git hooks/post-receive script.
andrewrk-guest pushed a commit to branch master
in repository node-findit2.
commit a154d549464bf8730ec1439ab32fc02d0bd1e1fc
Author: Andrew Kelley <superjoe30 at gmail.com>
Date: Fri Oct 17 22:47:44 2014 +0000
Imported Upstream version 2.2.2
---
.gitignore | 1 +
.travis.yml | 4 ++
LICENSE | 24 +++++++
README.md | 128 +++++++++++++++++++++++++++++++++
example/emitter.js | 16 +++++
index.js | 121 +++++++++++++++++++++++++++++++
package.json | 27 +++++++
test/empty.js | 17 +++++
test/err.js | 12 ++++
test/foo.js | 57 +++++++++++++++
test/foo/a/b/c/w | 0
test/foo/a/b/z | 0
test/foo/a/y | 0
test/foo/x | 0
test/module.js | 21 ++++++
test/stop.js | 33 +++++++++
test/stop/q/w/c | 0
test/stop/q/w/d | 0
test/stop/q/x | 0
test/stop/q/y | 0
test/stop/q/z/m | 0
test/stop/q/z/n | 0
test/stop/r/a | 0
test/stop/r/b | 0
test/stop/r/c/f/h | 0
test/stop/r/c/g/i | 0
test/symlinks.js | 92 ++++++++++++++++++++++++
test/symlinks/dir1/dangling-symlink | 1 +
test/symlinks/dir1/file1 | 0
test/symlinks/dir1/link-to-dir2 | 1 +
test/symlinks/dir1/link-to-file | 1 +
test/symlinks/dir2/cyclic-link-to-dir1 | 1 +
test/symlinks/dir2/file2 | 0
test/symlinks/file | 0
34 files changed, 557 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07e6e47
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/node_modules
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..cc4dba2
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - "0.8"
+ - "0.10"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..bbd17fc
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+The MIT License (Expat)
+
+Copyright (c) 2014 Andrew Kelley
+Copyright (c) 2014 James Halliday
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..86f6954
--- /dev/null
+++ b/README.md
@@ -0,0 +1,128 @@
+# findit
+
+Recursively walk directory trees. Think `/usr/bin/find`.
+
+[![build status](https://secure.travis-ci.org/andrewrk/node-findit.png)](http://travis-ci.org/andrewrk/node-findit)
+
+## Why the fork?
+
+There is a [pull request](https://github.com/substack/node-findit/pull/34) to
+merge this project back into findit.
+
+The pull request fixes every open issue in findit, and it completely rewrites
+the code from the ground up.
+
+It also adds an additional feature regarding symlinks.
+
+I would love for substack to merge the pull request, but realistically it might
+not happen, and this code is objectively cleaner, more robust, and fixes
+several critical issues.
+
+I recommend depending on this module rather than the original findit. If the
+pull request is merged, however, I will add a deprecation notice to this module
+and happily hand the maintainer hat back to substack.
+
+# example
+
+``` js
+var finder = require('findit')(process.argv[2] || '.');
+var path = require('path');
+
+finder.on('directory', function (dir, stat, stop) {
+ var base = path.basename(dir);
+ if (base === '.git' || base === 'node_modules') stop()
+ else console.log(dir + '/')
+});
+
+finder.on('file', function (file, stat) {
+ console.log(file);
+});
+
+finder.on('link', function (link, stat) {
+ console.log(link);
+});
+```
+
+# methods
+
+``` js
+var findit = require('findit2')
+```
+
+## var finder = findit(basedir, opts)
+
+Return an event emitter `finder` that performs a recursive walk starting at
+`basedir`.
+
+If you set `opts.followSymlinks`, symlinks will be followed. Otherwise, a
+`'link'` event will fire but symlinked directories will not be walked.
+
+If `basedir` is actually a non-directory regular file, findit emits a single
+"file" event for it then emits "end".
+
+You can optionally specify a custom
+[fs](http://nodejs.org/docs/latest/api/fs.html)
+implementation with `opts.fs`. `opts.fs` should implement:
+
+* `opts.fs.readdir(dir, cb)`
+* `opts.fs.lstat(dir, cb)`
+* `opts.fs.readlink(dir, cb)` - optional if your stat objects from
+`opts.fs.lstat` never return true for `stat.isSymbolicLink()`
+
+## finder.stop()
+
+Stop the traversal. A `"stop"` event will fire and then no more events will
+fire.
+
+# events
+
+## finder.on('path', function (file, stat, linkPath) {})
+
+For each file, directory, and symlink `file`, this event fires.
+
+If `followSymlinks` is `true`, then `linkPath` will be defined when `file`
+was found via a symlink. In this situation, `linkPath` is the path including
+the symlink; `file` is the resolved actual location on disk.
+
+## finder.on('file', function (file, stat, linkPath) {})
+
+For each file, this event fires.
+
+## finder.on('directory', function (dir, stat, stop, linkPath) {})
+
+For each directory, this event fires with the path `dir`.
+
+Your callback may call `stop()` on the first tick to tell findit to stop walking
+the current directory.
+
+## finder.on('link', function (file, stat) {})
+
+For each symlink, this event fires.
+
+## finder.on('readlink', function (src, dst) {})
+
+Every time a symlink is read when `opts.followSymlinks` is on, this event fires.
+
+## finder.on('end', function () {})
+
+When the recursive walk is complete unless `finder.stop()` was called, this
+event fires.
+
+## finder.on('stop', function () {})
+
+When `finder.stop()` is called, this event fires.
+
+## finder.on('error', function (err) {})
+
+Whenever there is an error, this event fires. You can choose to ignore errors or
+stop the traversal using `finder.stop()`.
+
+You can always get the source of the error by checking `err.path`.
+
+# install
+
+With [npm](https://npmjs.org) do:
+
+```
+npm install findit2
+```
diff --git a/example/emitter.js b/example/emitter.js
new file mode 100644
index 0000000..4e05b81
--- /dev/null
+++ b/example/emitter.js
@@ -0,0 +1,16 @@
+var finder = require('../')(process.argv[2] || '.');
+var path = require('path');
+
+finder.on('directory', function (dir, stat, stop) {
+ var base = path.basename(dir);
+ if (base === '.git' || base === 'node_modules') stop()
+ else console.log(dir + '/')
+});
+
+finder.on('file', function (file, stat) {
+ console.log(file);
+});
+
+finder.on('link', function (link, stat) {
+ console.log(link);
+});
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..aa82454
--- /dev/null
+++ b/index.js
@@ -0,0 +1,121 @@
+var EventEmitter = require('events').EventEmitter;
+var fs = require('fs');
+var path = require('path');
+
+module.exports = findit;
+
+function findit(basedir, opts) {
+ opts = opts || {};
+ var followSymlinks = !!opts.followSymlinks;
+ var myFs = opts.fs || fs;
+ var emitter = new EventEmitter();
+ var stopped = false;
+ var pending = 0;
+ var seen = {};
+
+ emitter.stop = stop;
+ walkPath(basedir);
+ return emitter;
+
+ function recursiveReadDir(basedir, linkPath) {
+ pendStart();
+ myFs.readdir(basedir, function(err, entries) {
+ if (stopped) return;
+ if (err) {
+ handleError(err, basedir);
+ pendEnd();
+ return;
+ }
+ entries.forEach(function(entry) {
+ var fullPath = path.join(basedir, entry);
+ var fullLinkPath = linkPath && path.join(linkPath, entry);
+ walkPath(fullPath, fullLinkPath);
+ });
+ pendEnd();
+ });
+ }
+
+ function walkPath(fullPath, linkPath) {
+ pendStart();
+ myFs.lstat(fullPath, function(err, stats) {
+ if (stopped) return;
+ if (err) {
+ handleError(err, fullPath);
+ pendEnd();
+ return;
+ }
+ emitter.emit('path', fullPath, stats, linkPath);
+ var dirStopped = false;
+ if (stats.isDirectory()) {
+ if (seen[fullPath]) {
+ err = new Error("file system loop detected");
+ err.code = 'ELOOP';
+ handleError(err, fullPath);
+ pendEnd();
+ return;
+ }
+ seen[fullPath] = true;
+
+ emitter.emit('directory', fullPath, stats, stopDir, linkPath);
+ if (!dirStopped) recursiveReadDir(fullPath, linkPath);
+ } else if (stats.isFile()) {
+ if (!seen[fullPath]) {
+ seen[fullPath] = true;
+ emitter.emit('file', fullPath, stats, linkPath);
+ }
+ } else if (stats.isSymbolicLink()) {
+ emitter.emit('link', fullPath, stats, linkPath);
+ if (followSymlinks) recursiveReadLink(fullPath);
+ }
+ pendEnd();
+
+ function stopDir() {
+ dirStopped = true;
+ }
+ });
+ }
+
+ function recursiveReadLink(linkPath) {
+ pendStart();
+ myFs.readlink(linkPath, function(err, linkString) {
+ if (stopped) return;
+ if (err) {
+ handleError(err, linkPath);
+ pendEnd();
+ return;
+ }
+ var fullPath = path.join(path.dirname(linkPath), linkString);
+ emitter.emit('readlink', linkPath, fullPath);
+ walkPath(fullPath, linkPath);
+ pendEnd();
+ });
+ }
+
+ function stop() {
+ if (stopped) return;
+ stopped = true;
+ emitter.emit('stop');
+ }
+
+ function handleError(err, errPath) {
+ if (!err || stopped) return;
+ err.path = errPath;
+ emitter.emit('error', err);
+ }
+
+ function pendStart() {
+ pending += 1;
+ }
+
+ function pendEnd() {
+ if (stopped) return;
+ pending -= 1;
+ if (pending === 0) {
+ emitter.emit('end');
+ } else if (pending < 0) {
+ // this should never happen; if this gets thrown we need to debug findit
+ // and this stack trace will help.
+ throw new Error("pendEnd called too many times");
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0e4ddc6
--- /dev/null
+++ b/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "findit2",
+ "version": "2.2.2",
+ "description": "walk a directory tree recursively with events",
+ "main": "index.js",
+ "devDependencies": {
+ "tap": "~0.4.13",
+ "mkdirp": "~0.5.0"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/andrewrk/node-findit.git"
+ },
+ "keywords": [
+ "find",
+ "walk",
+ "directory",
+ "recursive",
+ "tree",
+ "traversal"
+ ],
+ "author": "Andrew Kelley <superjoe30 at gmail.com>",
+ "license": "MIT"
+}
diff --git a/test/empty.js b/test/empty.js
new file mode 100644
index 0000000..a44760b
--- /dev/null
+++ b/test/empty.js
@@ -0,0 +1,17 @@
+var mkdirp = require('mkdirp');
+var test = require('tap').test;
+var find = require('../');
+
+mkdirp.sync(__dirname + '/empty');
+
+test('empty', function (t) {
+ t.plan(1);
+ var w = find(__dirname + '/empty');
+ var files = [];
+ w.on('file', function (file) {
+ files.push(file);
+ });
+ w.on('end', function () {
+ t.deepEqual(files, []);
+ });
+});
diff --git a/test/err.js b/test/err.js
new file mode 100644
index 0000000..57ee575
--- /dev/null
+++ b/test/err.js
@@ -0,0 +1,12 @@
+var find = require('../');
+var test = require('tap').test;
+var path = require('path');
+
+test('error', function (t) {
+ t.plan(1);
+
+ var finder = find(__dirname + '/does/not/exist');
+ finder.on('error', function (err) {
+ t.equal(err.path, __dirname + '/does/not/exist');
+ });
+});
diff --git a/test/foo.js b/test/foo.js
new file mode 100644
index 0000000..301dc53
--- /dev/null
+++ b/test/foo.js
@@ -0,0 +1,57 @@
+var find = require('../');
+var test = require('tap').test;
+
+test('foo', function (t) {
+ var finder = find(__dirname + '/foo');
+ var ps = {};
+
+ var paths = []
+ finder.on('path', function (p, stat) {
+ paths.push(p);
+ ps[p] = stat.isDirectory();
+ });
+
+ var dirs = []
+ finder.on('directory', function (dir) {
+ dirs.push(dir);
+ });
+
+ var files = []
+ finder.on('file', function (file) {
+ files.push(file);
+ });
+
+ finder.on('end', function () {
+ var ref = {
+ '' : true,
+ 'a' : true,
+ 'a/b' : true,
+ 'a/b/c' : true,
+ 'x' : false,
+ 'a/y' : false,
+ 'a/b/z' : false,
+ 'a/b/c/w' : false,
+ };
+
+ 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).replace(/\/$/, '');
+ t.equal(ref[key], ps[file]);
+ if (ref[key]) {
+ t.ok(dirs.indexOf(file) >= 0);
+ count.dirs ++;
+ }
+ else {
+ t.ok(files.indexOf(file) >= 0);
+ count.files ++;
+ }
+ });
+
+ t.deepEqual(count.dirs, dirs.length);
+ t.deepEqual(count.files, files.length);
+ t.deepEqual(paths.sort(), Object.keys(ps).sort());
+ t.end();
+ });
+});
diff --git a/test/foo/a/b/c/w b/test/foo/a/b/c/w
new file mode 100644
index 0000000..e69de29
diff --git a/test/foo/a/b/z b/test/foo/a/b/z
new file mode 100644
index 0000000..e69de29
diff --git a/test/foo/a/y b/test/foo/a/y
new file mode 100644
index 0000000..e69de29
diff --git a/test/foo/x b/test/foo/x
new file mode 100644
index 0000000..e69de29
diff --git a/test/module.js b/test/module.js
new file mode 100644
index 0000000..3fda390
--- /dev/null
+++ b/test/module.js
@@ -0,0 +1,21 @@
+var find = require('../');
+var test = require('tap').test;
+
+test('single file', function (t) {
+ t.plan(2);
+
+ var finder = find(__filename);
+ var files = [];
+ finder.on('file', function (file) {
+ t.equal(file, __filename);
+ files.push(file);
+ });
+
+ finder.on('directory', function (dir) {
+ t.fail(dir);
+ });
+
+ finder.on('end', function () {
+ t.deepEqual(files, [ __filename ]);
+ });
+});
diff --git a/test/stop.js b/test/stop.js
new file mode 100644
index 0000000..4929b11
--- /dev/null
+++ b/test/stop.js
@@ -0,0 +1,33 @@
+var find = require('../');
+var test = require('tap').test;
+var path = require('path');
+
+test('stop', function (t) {
+ t.plan(1);
+
+ var finder = find(__dirname + '/..');
+ var files = [];
+ var stopped = false;
+ finder.on('file', function (file) {
+ files.push(file);
+ if (files.length === 3) {
+ finder.stop();
+ stopped = true;
+ }
+ else if (stopped) {
+ t.fail("files didn't stop");
+ }
+ });
+
+ finder.on('directory', function (dir, stat, stop) {
+ if (stopped) t.fail("directories didn't stop");
+ });
+
+ finder.on('end', function () {
+ t.fail("shouldn't have ended");
+ });
+
+ finder.on('stop', function () {
+ t.equal(files.length, 3);
+ });
+});
diff --git a/test/stop/q/w/c b/test/stop/q/w/c
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/q/w/d b/test/stop/q/w/d
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/q/x b/test/stop/q/x
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/q/y b/test/stop/q/y
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/q/z/m b/test/stop/q/z/m
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/q/z/n b/test/stop/q/z/n
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/r/a b/test/stop/r/a
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/r/b b/test/stop/r/b
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/r/c/f/h b/test/stop/r/c/f/h
new file mode 100644
index 0000000..e69de29
diff --git a/test/stop/r/c/g/i b/test/stop/r/c/g/i
new file mode 100644
index 0000000..e69de29
diff --git a/test/symlinks.js b/test/symlinks.js
new file mode 100644
index 0000000..cfff1e7
--- /dev/null
+++ b/test/symlinks.js
@@ -0,0 +1,92 @@
+var test = require('tap').test;
+var path = require('path');
+var findit = require('../');
+
+function helper(t, dir, options, callback) {
+ var symlinks = [];
+ var files = [];
+ var dirs = [];
+ var errors = [];
+
+ var finder = findit(dir, options);
+
+ finder.on('link', function (link, stat) {
+ t.ok(stat.isSymbolicLink());
+ symlinks.push(path.basename(link));
+ });
+
+ finder.on('file', function (file, stat) {
+ t.ok(stat.isFile());
+ files.push(path.basename(file));
+ });
+
+ finder.on('directory', function (dir, stat) {
+ t.ok(stat.isDirectory());
+ dirs.push(path.basename(dir));
+ });
+
+ finder.on('error', function (err) {
+ errors.push(err);
+ });
+
+ finder.on('end', function () {
+ symlinks.sort();
+ files.sort();
+ dirs.sort();
+
+ callback({
+ errors: errors,
+ symlinks: symlinks,
+ files: files,
+ dirs: dirs
+ });
+ });
+}
+
+test('links', function (t) {
+ helper(t, __dirname + '/symlinks/dir1', { followSymlinks: false }, done);
+ function done (data) {
+ t.deepEqual(data.errors, []);
+ t.deepEqual(data.symlinks, [
+ 'dangling-symlink', 'link-to-dir2', 'link-to-file'
+ ]);
+ t.deepEqual(data.files, [ 'file1' ]);
+ t.deepEqual(data.dirs, [ 'dir1' ]);
+ t.end();
+ }
+});
+test('follow links', function (t) {
+ helper(t, __dirname + '/symlinks/dir1', { followSymlinks: true }, done);
+
+ function done (data) {
+ t.equal(data.errors.length, 2);
+ t.equal(
+ data.errors[0].path, __dirname + '/symlinks/dir1/does-not-exist'
+ );
+ t.equal(
+ data.errors[1].path, __dirname + '/symlinks/dir1'
+ );
+
+ 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' ]);
+ t.end();
+ }
+});
+
+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();
+ }
+});
diff --git a/test/symlinks/dir1/dangling-symlink b/test/symlinks/dir1/dangling-symlink
new file mode 120000
index 0000000..cfa0a46
--- /dev/null
+++ b/test/symlinks/dir1/dangling-symlink
@@ -0,0 +1 @@
+does-not-exist
\ No newline at end of file
diff --git a/test/symlinks/dir1/file1 b/test/symlinks/dir1/file1
new file mode 100644
index 0000000..e69de29
diff --git a/test/symlinks/dir1/link-to-dir2 b/test/symlinks/dir1/link-to-dir2
new file mode 120000
index 0000000..d014eb4
--- /dev/null
+++ b/test/symlinks/dir1/link-to-dir2
@@ -0,0 +1 @@
+../dir2
\ No newline at end of file
diff --git a/test/symlinks/dir1/link-to-file b/test/symlinks/dir1/link-to-file
new file mode 120000
index 0000000..74bb61d
--- /dev/null
+++ b/test/symlinks/dir1/link-to-file
@@ -0,0 +1 @@
+../file
\ No newline at end of file
diff --git a/test/symlinks/dir2/cyclic-link-to-dir1 b/test/symlinks/dir2/cyclic-link-to-dir1
new file mode 120000
index 0000000..c9f3ab1
--- /dev/null
+++ b/test/symlinks/dir2/cyclic-link-to-dir1
@@ -0,0 +1 @@
+../dir1
\ No newline at end of file
diff --git a/test/symlinks/dir2/file2 b/test/symlinks/dir2/file2
new file mode 100644
index 0000000..e69de29
diff --git a/test/symlinks/file b/test/symlinks/file
new file mode 100644
index 0000000..e69de29
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-findit2.git
More information about the Pkg-javascript-commits
mailing list