[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