[Pkg-javascript-commits] [node-readdirp] 01/09: New upstream version 2.1.0

Praveen Arimbrathodiyil praveen at moszumanska.debian.org
Mon May 15 09:48:47 UTC 2017


This is an automated email from the git hooks/post-receive script.

praveen pushed a commit to branch master
in repository node-readdirp.

commit 1b2e944dcd81fdda31154d1acd26b2cd731557d1
Author: Pirate Praveen <praveen at debian.org>
Date:   Mon May 15 12:40:22 2017 +0530

    New upstream version 2.1.0
---
 .travis.yml                 |   7 +-
 LICENSE                     |  32 ++++---
 README.md                   |  16 ++--
 examples/grep.js            |   2 -
 examples/stream-api-pipe.js |  14 ++-
 package.json                |  25 ++++--
 readdirp.js                 |  57 ++++++++++---
 stream-api.js               | 155 ++++++++++++++++++----------------
 test/readdirp-stream.js     | 201 +++++++++++++++++++++++++++++++++++---------
 test/readdirp.js            |  67 +++++++++++----
 10 files changed, 403 insertions(+), 173 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 84fd7ca..0cdb6c3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
 language: node_js
 node_js:
-  - 0.6
-  - 0.8
-  - 0.9
+  - "0.10"
+  - "0.12"
+  - "4.4"
+  - "6.2"
diff --git a/LICENSE b/LICENSE
index de78e27..8a63b80 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,16 +1,20 @@
-lib-cov
-*.seed
-*.log
-*.csv
-*.dat
-*.out
-*.pid
-*.gz
+This software is released under the MIT license:
 
-pids
-logs
-results
+Copyright (c) 2012-2015 Thorsten Lorenz
 
-node_modules
-npm-debug.log
-tmp
+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
index 7b36a8a..b0c1626 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
 # readdirp [![Build Status](https://secure.travis-ci.org/thlorenz/readdirp.png)](http://travis-ci.org/thlorenz/readdirp)
 
+[![NPM](https://nodei.co/npm/readdirp.png?downloads=true&stars=true)](https://nodei.co/npm/readdirp/)
+
 Recursive version of [fs.readdir](http://nodejs.org/docs/latest/api/fs.html#fs_fs_readdir_path_callback). Exposes a **stream api**.
 
 ```javascript
-var readdirp = require('readdirp'); 
+var readdirp = require('readdirp')
   , path = require('path')
   , es = require('event-stream');
 
@@ -66,10 +68,10 @@ Behaves as follows:
 - `emit('close')` called when the stream is destroyed via `stream.destroy()` (which could be useful if you want to
   manually abort even on a non fatal error) - at that point the stream is no longer `readable` and no more entries,
   warning or errors are emitted
-- the stream is `paused` initially in order to allow `pipe` and `on` handlers be connected before data or errors are
-  emitted
-- the stream is `resumed` automatically during the next event loop 
-- to learn more about streams, consult the [stream-handbook](https://github.com/substack/stream-handbook)
+- to learn more about streams, consult the very detailed 
+  [nodejs streams documentation](http://nodejs.org/api/stream.html) or the
+  [stream-handbook](https://github.com/substack/stream-handbook)
+  
 
 ## options
     
@@ -81,6 +83,10 @@ Behaves as follows:
 
 - **depth**: depth at which to stop recursing even if more subdirectories are found
 
+- **entryType**: determines if data events on the stream should be emitted for `'files'`, `'directories'`, `'both'`, or `'all'`. Setting to `'all'` will also include entries for other types of file descriptors like character devices, unix sockets and named pipes. Defaults to `'files'`.
+
+- **lstat**: if `true`, readdirp uses `fs.lstat` instead of `fs.stat` in order to stat files and includes symlink entries in the stream along with files.
+
 ## entry info
 
 Has the following properties:
diff --git a/examples/grep.js b/examples/grep.js
index 807fa35..01d5f29 100644
--- a/examples/grep.js
+++ b/examples/grep.js
@@ -3,8 +3,6 @@ var readdirp =  require('..')
   , util     =  require('util')
   , fs       =  require('fs')
   , path     =  require('path')
-  , Stream   =  require('stream')
-  , tap      =  require('tap-stream')
   , es       =  require('event-stream')
   ;
 
diff --git a/examples/stream-api-pipe.js b/examples/stream-api-pipe.js
index b09fe59..4003be8 100644
--- a/examples/stream-api-pipe.js
+++ b/examples/stream-api-pipe.js
@@ -1,13 +1,19 @@
 var readdirp =  require('..')
   , path = require('path')
-  , es = require('event-stream');
+  , through = require('through2')
 
 // print out all JavaScript files along with their size
 readdirp({ root: path.join(__dirname), fileFilter: '*.js' })
   .on('warn', function (err) { console.error('non-fatal error', err); })
   .on('error', function (err) { console.error('fatal error', err); })
-  .pipe(es.mapSync(function (entry) { 
-    return { path: entry.path, size: entry.stat.size };
+  .pipe(through.obj(function (entry, _, cb) { 
+    this.push({ path: entry.path, size: entry.stat.size });
+    cb();
   }))
-  .pipe(es.stringify())
+  .pipe(through.obj(
+    function (res, _, cb) { 
+      this.push(JSON.stringify(res) + '\n');
+      cb();
+    })
+  )
   .pipe(process.stdout);
diff --git a/package.json b/package.json
index 8eeb958..ca02cde 100644
--- a/package.json
+++ b/package.json
@@ -2,14 +2,14 @@
   "author": "Thorsten Lorenz <thlorenz at gmx.de> (thlorenz.com)",
   "name": "readdirp",
   "description": "Recursive version of fs.readdir with streaming api.",
-  "version": "0.2.4",
+  "version": "2.1.0",
   "homepage": "https://github.com/thlorenz/readdirp",
   "repository": {
     "type": "git",
     "url": "git://github.com/thlorenz/readdirp.git"
   },
   "engines": {
-    "node": ">=0.4"
+    "node": ">=0.6"
   },
   "keywords": [
     "recursive",
@@ -23,16 +23,25 @@
   ],
   "main": "readdirp.js",
   "scripts": {
-    "test": "tap test/*.js"
+    "test-main": "(cd test && set -e; for t in ./*.js; do node $t; done)",
+    "test-0.10": "nave use 0.10 npm run test-main",
+    "test-0.12": "nave use 0.12 npm run test-main",
+    "test-4": "nave use 4.4 npm run test-main",
+    "test-6": "nave use 6.2 npm run test-main",
+    "test-all": "npm run test-main && npm run test-0.10 && npm run test-0.12 && npm run test-4 && npm run test-6",
+    "test": "if [ -e $TRAVIS ]; then npm run test-all; else npm run test-main; fi"
   },
   "dependencies": {
-    "minimatch": ">=0.2.4"
+    "graceful-fs": "^4.1.2",
+    "minimatch": "^3.0.2",
+    "readable-stream": "^2.0.2",
+    "set-immediate-shim": "^1.0.1"
   },
   "devDependencies": {
-    "tap": "~0.3.1",
-    "through": "~1.1.0",
-    "minimatch": "~0.2.7"
+    "nave": "^0.5.1",
+    "proxyquire": "^1.7.9",
+    "tap": "1.3.2",
+    "through2": "^2.0.0"
   },
-  "optionalDependencies": {},
   "license": "MIT"
 }
diff --git a/readdirp.js b/readdirp.js
index 03bfcd7..b6b21e4 100644
--- a/readdirp.js
+++ b/readdirp.js
@@ -1,22 +1,24 @@
 'use strict';
 
-var fs        =  require('fs')
+var fs        =  require('graceful-fs')
   , path      =  require('path')
   , minimatch =  require('minimatch')
   , toString  =  Object.prototype.toString
+  , si        =  require('set-immediate-shim')
   ;
 
+
 // Standard helpers
 function isFunction (obj) {
-  return toString.call(obj) == '[object Function]';
+  return toString.call(obj) === '[object Function]';
 }
 
 function isString (obj) {
-  return toString.call(obj) == '[object String]';
+  return toString.call(obj) === '[object String]';
 }
 
 function isRegExp (obj) {
-  return toString.call(obj) == '[object RegExp]';
+  return toString.call(obj) === '[object RegExp]';
 }
 
 function isUndefined (obj) {
@@ -45,6 +47,7 @@ function readdir(opts, callback1, callback2) {
     , allProcessed
     , realRoot
     , aborted = false
+    , paused = false
     ;
 
   // If no callbacks were given we will use a streaming interface
@@ -57,6 +60,8 @@ function readdir(opts, callback1, callback2) {
     handleFatalError =  api.handleFatalError;
 
     stream.on('close', function () { aborted = true; });
+    stream.on('pause', function () { paused = true; });
+    stream.on('resume', function () { paused = false; });
   } else {
     handleError      =  function (err) { errors.push(err); };
     handleFatalError =  function (err) {
@@ -78,6 +83,9 @@ function readdir(opts, callback1, callback2) {
   opts.fileFilter      =  opts.fileFilter      || function() { return true; };
   opts.directoryFilter =  opts.directoryFilter || function() { return true; };
   opts.depth           =  typeof opts.depth === 'undefined' ? 999999999 : opts.depth;
+  opts.entryType       =  opts.entryType       || 'files';
+
+  var statfn = opts.lstat === true ? fs.lstat.bind(fs) : fs.stat.bind(fs);
 
   if (isUndefined(callback2)) {
     fileProcessed = function() { };
@@ -156,6 +164,11 @@ function readdir(opts, callback1, callback2) {
 
     fs.realpath(currentDir, function(err, realCurrentDir) {
       if (aborted) return;
+      if (err) {
+        handleError(err);
+        callProcessed(entryInfos);
+        return;
+      }
 
       var relDir = path.relative(realRoot, realCurrentDir);
 
@@ -164,10 +177,10 @@ function readdir(opts, callback1, callback2) {
       } else {
         entries.forEach(function (entry) { 
 
-          var fullPath = path.join(realCurrentDir, entry),
-            relPath  = path.join(relDir, entry);
+          var fullPath = path.join(realCurrentDir, entry)
+            , relPath  = path.join(relDir, entry);
 
-          fs.stat(fullPath, function (err, stat) {
+          statfn(fullPath, function (err, stat) {
             if (err) {
               handleError(err);
             } else {
@@ -191,7 +204,14 @@ function readdir(opts, callback1, callback2) {
   }
 
   function readdirRec(currentDir, depth, callCurrentDirProcessed) {
+    var args = arguments;
     if (aborted) return;
+    if (paused) {
+      si(function () {
+        readdirRec.apply(null, args);
+      })
+      return;
+    } 
 
     fs.readdir(currentDir, function (err, entries) {
       if (err) {
@@ -205,14 +225,23 @@ function readdir(opts, callback1, callback2) {
         var subdirs = entryInfos
           .filter(function (ei) { return ei.stat.isDirectory() && opts.directoryFilter(ei); });
 
-        subdirs.forEach(function (di) { 
+        subdirs.forEach(function (di) {
+          if(opts.entryType === 'directories' || opts.entryType === 'both' || opts.entryType === 'all') {
+            fileProcessed(di);
+          }
           readdirResult.directories.push(di); 
         });
 
         entryInfos
-          .filter(function(ei) { return ei.stat.isFile() && opts.fileFilter(ei); })
-          .forEach(function (fi) { 
-            fileProcessed(fi);
+          .filter(function(ei) {
+            var isCorrectType = opts.entryType === 'all' ?
+              !ei.stat.isDirectory() : ei.stat.isFile() || ei.stat.isSymbolicLink();
+            return isCorrectType && opts.fileFilter(ei);
+          })
+          .forEach(function (fi) {
+            if(opts.entryType === 'files' || opts.entryType === 'both' || opts.entryType === 'all') {
+              fileProcessed(fi);
+            }
             readdirResult.files.push(fi); 
           });
 
@@ -249,7 +278,11 @@ function readdir(opts, callback1, callback2) {
 
   // If filters were valid get on with the show
   fs.realpath(opts.root, function(err, res) {
-    
+    if (err) {
+      handleFatalError(err);
+      return stream;
+    }
+
     realRoot = res;
     readdirRec(opts.root, 0, function () { 
       // All errors are collected into the errors array
diff --git a/stream-api.js b/stream-api.js
index 1cfc616..91c6808 100644
--- a/stream-api.js
+++ b/stream-api.js
@@ -1,85 +1,98 @@
-var Stream = require('stream');
+'use strict';
 
-function createStreamAPI () {
-  var stream
-    , processEntry
-    , done
-    , handleError
-    , handleFatalError
-    , paused = true
-    , controlled = false
-    , buffer = []
-    , closed = false
-    ;
-
-  stream = new Stream();
-  stream.writable = false;
-  stream.readable = true;
-
-  stream.pause = function () {
-    controlled = true;
-    paused = true;
-  };
+var si =  require('set-immediate-shim');
+var stream = require('readable-stream');
+var util = require('util');
 
-  stream.resume = function () {
-    controlled = true;
-    paused = false;
-    
-    // emit all buffered entries, errors and ends
-    while (!paused && buffer.length) {
-      var msg = buffer.shift();
-      this.emit(msg.type, msg.data);
-    }
-  };
+var Readable = stream.Readable;
 
-  stream.destroy = function () {
-    closed = true;
-    stream.readable = false;
-    stream.emit('close');
-  };
+module.exports = ReaddirpReadable;
 
-  // called for each entry
-  processEntry = function (entry) {
-    if (closed) return;
-    return paused ? buffer.push({ type: 'data', data: entry }) : stream.emit('data', entry);
-  };
+util.inherits(ReaddirpReadable, Readable);
 
-  // called with all found entries when directory walk finished
-  done = function (err, entries) {
-    if (closed) return;
-    
-    // since we already emitted each entry and all non fatal errors
-    // all we need to do here is to signal that we are done
-    stream.emit('end');
-  };
+function ReaddirpReadable (opts) {
+  if (!(this instanceof ReaddirpReadable)) return new ReaddirpReadable(opts);
 
-  handleError = function (err) {
-    if (closed) return;
-    return paused ? buffer.push({ type: 'warn', data: err }) : stream.emit('warn', err);
-  };
+  opts = opts || {};
 
-  handleFatalError = function (err) {
-    if (closed) return;
-    return paused ? buffer.push({ type: 'error', data: err }) : stream.emit('error', err);
-  };
+  opts.objectMode = true;
+  Readable.call(this, opts);
+
+  // backpressure not implemented at this point
+  this.highWaterMark = Infinity;
+
+  this._destroyed = false;
+  this._paused = false;
+  this._warnings = [];
+  this._errors = [];
+
+  this._pauseResumeErrors();
+}
+
+var proto = ReaddirpReadable.prototype;
+
+proto._pauseResumeErrors = function () {
+  var self = this;
+  self.on('pause', function () { self._paused = true });
+  self.on('resume', function () {
+    if (self._destroyed) return;
+    self._paused = false;
+
+    self._warnings.forEach(function (err) { self.emit('warn', err) });
+    self._warnings.length = 0;
 
-  // Allow stream to be returned and handlers to be attached and/or stream to be piped before emitting messages
-  // Otherwise we may loose data/errors that are emitted immediately
-  process.nextTick(function () { 
-    if (closed) return;
-    
-    // In case was controlled (paused/resumed) manually, we don't interfer
-    // see https://github.com/thlorenz/readdirp/commit/ab7ff8561d73fca82c2ce7eb4ce9f7f5caf48b55#commitcomment-1964530
-    if (controlled) return;
-    stream.resume(); 
+    self._errors.forEach(function (err) { self.emit('error', err) });
+    self._errors.length = 0;
+  })
+}
+
+// called for each entry
+proto._processEntry = function (entry) {
+  if (this._destroyed) return;
+  this.push(entry);
+}
+
+proto._read = function () { }
+
+proto.destroy = function () {
+  // when stream is destroyed it will emit nothing further, not even errors or warnings
+  this.push(null);
+  this.readable = false;
+  this._destroyed = true;
+  this.emit('close');
+}
+
+proto._done = function () {
+  this.push(null);
+}
+
+// we emit errors and warnings async since we may handle errors like invalid args
+// within the initial event loop before any event listeners subscribed
+proto._handleError = function (err) {
+  var self = this;
+  si(function () {
+    if (self._paused) return self._warnings.push(err);
+    if (!self._destroyed) self.emit('warn', err);
+  });
+}
+
+proto._handleFatalError = function (err) {
+  var self = this;
+  si(function () {
+    if (self._paused) return self._errors.push(err);
+    if (!self._destroyed) self.emit('error', err);
   });
+}
+
+function createStreamAPI () {
+  var stream = new ReaddirpReadable();
 
-  return { 
+  return {
       stream           :  stream
-    , processEntry     :  processEntry
-    , done             :  done
-    , handleError      :  handleError
-    , handleFatalError :  handleFatalError
+    , processEntry     :  stream._processEntry.bind(stream)
+    , done             :  stream._done.bind(stream)
+    , handleError      :  stream._handleError.bind(stream)
+    , handleFatalError :  stream._handleFatalError.bind(stream)
   };
 }
 
diff --git a/test/readdirp-stream.js b/test/readdirp-stream.js
index 261c5f6..c43d132 100644
--- a/test/readdirp-stream.js
+++ b/test/readdirp-stream.js
@@ -1,19 +1,22 @@
 /*jshint asi:true */
 
-var test      =  require('tap').test
-  , path      =  require('path')
-  , fs        =  require('fs')
-  , util      =  require('util')
-  , Stream    =  require('stream')
-  , through   =  require('through')
-  , streamapi =  require('../stream-api')
-  , readdirp  =  require('..')
-  , root       =  path.join(__dirname, 'bed')
-  , totalDirs  =  6
-  , totalFiles =  12
-  , ext1Files  =  4
-  , ext2Files  =  3
-  , ext3Files  =  2
+var debug           //= true;
+var test            = debug  ? function () {} : require('tap').test
+var test_           = !debug ? function () {} : require('tap').test
+  , path            = require('path')
+  , fs              = require('fs')
+  , util            = require('util')
+  , TransformStream = require('readable-stream').Transform
+  , through         = require('through2')
+  , proxyquire      = require('proxyquire')
+  , streamapi       = require('../stream-api')
+  , readdirp        = require('..')
+  , root            = path.join(__dirname, 'bed')
+  , totalDirs       = 6
+  , totalFiles      = 12
+  , ext1Files       = 4
+  , ext2Files       = 3
+  , ext3Files       = 2
   ;
   
 // see test/readdirp.js for test bed layout
@@ -31,19 +34,17 @@ function opts (extend) {
 
 function capture () {
   var result = { entries: [], errors: [], ended: false }
-    , dst = new Stream();
+    , dst = new TransformStream({ objectMode: true });
 
-  dst.writable = true;
-  dst.readable = true;
-
-  dst.write = function (entry) {
+  dst._transform = function (entry, _, cb) {
     result.entries.push(entry);
+    cb();
   }
 
-  dst.end = function () {
+  dst._flush = function (cb) {
     result.ended = true;
-    dst.emit('data', result);
-    dst.emit('end');
+    this.push(result); 
+    cb();
   }
 
   return dst;
@@ -52,16 +53,18 @@ function capture () {
 test('\nintegrated', function (t) {
   t.test('\n# reading root without filter', function (t) {
     t.plan(2);
+
     readdirp(opts())
       .on('error', function (err) {
         t.fail('should not throw error', err);
       })
       .pipe(capture())
-      .pipe(through(
-        function (result) { 
+      .pipe(through.obj(
+        function (result, _ , cb) { 
           t.equals(result.entries.length, totalFiles, 'emits all files');
           t.ok(result.ended, 'ends stream');
           t.end();
+          cb();
         }
       ));
   })
@@ -74,11 +77,102 @@ test('\nintegrated', function (t) {
         t.fail('should not throw error', err);
       })
       .pipe(capture())
-      .pipe(through(
-        function (result) { 
+      .pipe(through.obj(
+        function (result, _ , cb) { 
           t.equals(result.entries.length, ext1Files + ext3Files, 'all ext1 and ext3 files');
           t.ok(result.ended, 'ends stream');
           t.end();
+          cb();
+        }
+      ))
+  })
+
+  t.test('\n# files only', function (t) {
+    t.plan(2);
+
+    readdirp(opts( { entryType: 'files' } ))
+      .on('error', function (err) {
+        t.fail('should not throw error', err);
+      })
+      .pipe(capture())
+      .pipe(through.obj(
+        function (result, _ , cb) { 
+          t.equals(result.entries.length, totalFiles, 'returned files');
+          t.ok(result.ended, 'ends stream');
+          t.end();
+          cb();
+        }
+      ))
+  })
+
+  t.test('\n# directories only', function (t) {
+    t.plan(2);
+
+    readdirp(opts( { entryType: 'directories' } ))
+      .on('error', function (err) {
+        t.fail('should not throw error', err);
+      })
+      .pipe(capture())
+      .pipe(through.obj(
+        function (result, _ , cb) { 
+          t.equals(result.entries.length, totalDirs, 'returned directories');
+          t.ok(result.ended, 'ends stream');
+          t.end();
+          cb();
+        }
+      ))
+  })
+
+  t.test('\n# both directories + files', function (t) {
+    t.plan(2);
+
+    readdirp(opts( { entryType: 'both' } ))
+      .on('error', function (err) {
+        t.fail('should not throw error', err);
+      })
+      .pipe(capture())
+      .pipe(through.obj(
+        function (result, _ , cb) { 
+          t.equals(result.entries.length, totalDirs + totalFiles, 'returned everything');
+          t.ok(result.ended, 'ends stream');
+          t.end();
+          cb();
+        }
+      ))
+  })
+
+  t.test('\n# directory filter with directories only', function (t) {
+    t.plan(2);
+
+    readdirp(opts( { entryType: 'directories', directoryFilter: [ 'root_dir1', '*dir1_subdir1' ] } ))
+      .on('error', function (err) {
+        t.fail('should not throw error', err);
+      })
+      .pipe(capture())
+      .pipe(through.obj(
+        function (result, _ , cb) {
+          t.equals(result.entries.length, 2, 'two directories');
+          t.ok(result.ended, 'ends stream');
+          t.end();
+          cb();
+        }
+      ))
+  })
+
+  t.test('\n# directory and file filters with both entries', function (t) {
+    t.plan(2);
+
+    readdirp(opts( { entryType: 'both', directoryFilter: [ 'root_dir1', '*dir1_subdir1' ], fileFilter: [ '!*.ext1' ] } ))
+      .on('error', function (err) {
+        t.fail('should not throw error', err);
+      })
+      .pipe(capture())
+      .pipe(through.obj(
+        function (result, _ , cb) {
+          t.equals(result.entries.length, 6, '2 directories and 4 files');
+          t.ok(result.ended, 'ends stream');
+          t.end();
+          cb();
         }
       ))
   })
@@ -91,8 +185,8 @@ test('\nintegrated', function (t) {
         t.fail('should not throw error', err);
       })
       .pipe(capture())
-      .pipe(through(
-        function (result) { 
+      .pipe(through.obj(
+        function (result, _ , cb) { 
           t.equals(result.entries.length, totalFiles - ext1Files - ext3Files, 'all but ext1 and ext3 files');
           t.ok(result.ended, 'ends stream');
           t.end();
@@ -164,32 +258,61 @@ test('\napi separately', function (t) {
     api.handleError(nonfatalError);
     api.handleFatalError(fatalError);
   
-    process.nextTick(function () {
+    setTimeout(function () {
       resumed = true;
       api.stream.resume();
-    })
+    }, 1)
+  })
+
+  t.test('\n# when a stream is paused it stops walking the fs', function (t) {
+    var resumed = false,
+      mockedAPI = streamapi();
+
+    mockedAPI.processEntry = function (entry) {
+      if (!resumed) t.notOk(true, 'should not emit while paused')
+      t.ok(entry, 'emitted while resumed')
+    }.bind(mockedAPI.stream)
+
+    function wrapper () {
+      return mockedAPI
+    }
+
+    var readdirp = proxyquire('../readdirp', {'./stream-api': wrapper})
+      , stream = readdirp(opts())
+      .on('error', function (err) {
+        t.fail('should not throw error', err);
+      })
+      .on('end', function () {
+        t.end()
+      })
+      .pause();
+
+    setTimeout(function () {
+      resumed = true;
+      stream.resume();
+    }, 5)
   })
 
   t.test('\n# when a stream is destroyed, it emits "closed", but no longer emits "data", "warn" and "error"', function (t) {
-    t.plan(6)
     var api = streamapi()
-      , destroyed = false
       , fatalError = new Error('fatal!')
       , nonfatalError = new Error('nonfatal!')
       , processedData = 'some data'
+      , plan = 0;
 
+    t.plan(6)
     var stream = api.stream
       .on('warn', function (err) {
-        t.notOk(destroyed, 'emits warning until destroyed');
+        t.ok(!stream._destroyed, 'emits warning until destroyed');
       })
       .on('error', function (err) {
-        t.notOk(destroyed, 'emits errors until destroyed');
+        t.ok(!stream._destroyed, 'emits errors until destroyed');
       })
       .on('data', function (data) {
-        t.notOk(destroyed, 'emits data until destroyed');
+        t.ok(!stream._destroyed, 'emits data until destroyed');
       })
       .on('close', function () {
-        t.ok(destroyed, 'emits close when stream is destroyed');
+        t.ok(stream._destroyed, 'emits close when stream is destroyed');
       })
     
 
@@ -197,8 +320,7 @@ test('\napi separately', function (t) {
     api.handleError(nonfatalError);
     api.handleFatalError(fatalError);
 
-    process.nextTick(function () {
-      destroyed = true
+    setTimeout(function () {
       stream.destroy()
 
       t.notOk(stream.readable, 'stream is no longer readable after it is destroyed')
@@ -209,7 +331,8 @@ test('\napi separately', function (t) {
 
       process.nextTick(function () {
         t.pass('emits no more data, warn or error events after it was destroyed')  
+        t.end();
       })
-    })
+    }, 10)
   })
 })
diff --git a/test/readdirp.js b/test/readdirp.js
index f3edb52..812afbb 100644
--- a/test/readdirp.js
+++ b/test/readdirp.js
@@ -1,11 +1,12 @@
 /*jshint asi:true */
 
-var test     =  require('tap').test
-  , path     =  require('path')
-  , fs       =  require('fs')
-  , util     =  require('util')
-  , readdirp =  require('../readdirp.js')
-  , root     =  path.join(__dirname, '../test/bed')
+var test     = require('tap').test
+  , path     = require('path')
+  , fs       = require('fs')
+  , util     = require('util')
+  , net      = require('net')
+  , readdirp = require('../readdirp.js')
+  , root     = path.join(__dirname, '../test/bed')
   , totalDirs          =  6
   , totalFiles         =  12
   , ext1Files          =  4
@@ -17,7 +18,7 @@ var test     =  require('tap').test
   , depth0Files        =  3
   ;
 
-/* 
+/*
 Structure of test bed:
     .
     ├── root_dir1
@@ -61,7 +62,43 @@ test('\nreading root without filter', function (t) {
     t.equals(res.directories.length, totalDirs, 'all directories');
     t.equals(res.files.length, totalFiles, 'all files');
     t.end();
-  }) 
+  })
+})
+
+test('\nreading root without filter using lstat', function (t) {
+  t.plan(2);
+  readdirp(opts({ lstat: true }), function (err, res) {
+    t.equals(res.directories.length, totalDirs, 'all directories');
+    t.equals(res.files.length, totalFiles, 'all files');
+    t.end();
+  })
+})
+
+test('\nreading root with symlinks using lstat', function (t) {
+  t.plan(2);
+  fs.symlinkSync(path.join(root, 'root_dir1'), path.join(root, 'dirlink'));
+  fs.symlinkSync(path.join(root, 'root_file1.ext1'), path.join(root, 'link.ext1'));
+  readdirp(opts({ lstat: true }), function (err, res) {
+    t.equals(res.directories.length, totalDirs, 'all directories');
+    t.equals(res.files.length, totalFiles + 2, 'all files + symlinks');
+    fs.unlinkSync(path.join(root, 'dirlink'));
+    fs.unlinkSync(path.join(root, 'link.ext1'));
+    t.end();
+  })
+})
+
+test('\nreading non-standard fds', function (t) {
+  t.plan(2);
+  var server = net.createServer().listen(path.join(root, 'test.sock'), function(){
+    readdirp(opts({ entryType: 'all' }), function (err, res) {
+      t.equals(res.files.length, totalFiles + 1, 'all files + socket');
+      readdirp(opts({ entryType: 'both' }), function (err, res) {
+        t.equals(res.files.length, totalFiles, 'all regular files only');
+        server.close();
+        t.end();
+      })
+    })
+  });
 })
 
 test('\nreading root using glob filter', function (t) {
@@ -153,7 +190,7 @@ test('\n\nreading root using function filter', function (t) {
       }
     )
   })
-  
+
   t.test('\n# directory filter -> "name has length 9"', function (t) {
     t.plan(1);
     readdirp(
@@ -191,10 +228,10 @@ test('\nprogress callbacks', function (t) {
     , processedFiles = [];
 
   readdirp(
-      opts() 
-    , function(fi) { 
+      opts()
+    , function(fi) {
         processedFiles.push(fi);
-      } 
+      }
     , function (err, res) {
         t.equals(processedFiles.length, res.files.length, 'calls back for each file processed');
         t.deepEquals(processedFiles.map(pluckName).sort(),res.files.map(pluckName).sort(), 'same file names');
@@ -204,13 +241,13 @@ test('\nprogress callbacks', function (t) {
 })
 
 test('resolving of name, full and relative paths', function (t) {
-  var expected = {  
+  var expected = {
         name          :  'root_dir1_file1.ext1'
       , parentDirName :  'root_dir1'
       , path          :  'root_dir1/root_dir1_file1.ext1'
       , fullPath      :  'test/bed/root_dir1/root_dir1_file1.ext1'
       }
-    , opts = [ 
+    , opts = [
         { root: './bed'          ,  prefix: ''     }
       , { root: './bed/'         ,  prefix: ''     }
       , { root: 'bed'            ,  prefix: ''     }
@@ -219,7 +256,7 @@ test('resolving of name, full and relative paths', function (t) {
       , { root: '.'              ,  prefix: 'bed'  }
     ]
   t.plan(opts.length);
-  
+
   opts.forEach(function (op) {
     op.fileFilter = 'root_dir1_file1.ext1';
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-readdirp.git



More information about the Pkg-javascript-commits mailing list