[Pkg-javascript-commits] [node-rimraf] 01/15: New upstream version 2.5.4

Jérémy Lal kapouer at moszumanska.debian.org
Thu Nov 24 08:43:44 UTC 2016


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

kapouer pushed a commit to branch master
in repository node-rimraf.

commit 075daf32eb3c103c21db32bdc0afab71f05521be
Author: Jérémy Lal <kapouer at melix.org>
Date:   Thu Nov 24 09:19:41 2016 +0100

    New upstream version 2.5.4
---
 .gitignore         |   4 ++
 .travis.yml        |   8 +++
 AUTHORS            |   6 --
 LICENSE            |  32 ++++-----
 README.md          |  79 +++++++++++++++++++--
 bin.js             |  15 ++--
 package.json       |  24 +++++--
 rimraf.js          | 201 +++++++++++++++++++++++++++++++++++++++--------------
 test/basic.js      | 106 ++++++++++++++++++++++++++++
 test/custom-fs.js  | 187 +++++++++++++++++++++++++++++++++++++++++++++++++
 test/fill.js       |  41 +++++++++++
 test/run.sh        |  16 -----
 test/setup.sh      |  47 -------------
 test/test-async.js |   5 --
 test/test-sync.js  |   3 -
 15 files changed, 609 insertions(+), 165 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ab54836
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+node_modules/
+npm-debug.log
+.nyc_output
+coverage
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..ee45280
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+sudo: false
+language: node_js
+node_js:
+  - '0.10'
+  - '0.12'
+  - '4'
+  - '5'
+  - '6'
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index 247b754..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Authors sorted by whether or not they're me.
-Isaac Z. Schlueter <i at izs.me> (http://blog.izs.me)
-Wayne Larsen <wayne at larsen.st> (http://github.com/wvl)
-ritch <skawful at gmail.com>
-Marcel Laverdet
-Yosef Dinerstein <yosefd at microsoft.com>
diff --git a/LICENSE b/LICENSE
index 05a4010..19129e3 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,23 +1,15 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
-All rights reserved.
+The ISC License
 
-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:
+Copyright (c) Isaac Z. Schlueter and Contributors
 
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
 
-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.
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/README.md b/README.md
index cd123b6..423b8cf 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,89 @@
-`rm -rf` for node.
+[![Build Status](https://travis-ci.org/isaacs/rimraf.svg?branch=master)](https://travis-ci.org/isaacs/rimraf) [![Dependency Status](https://david-dm.org/isaacs/rimraf.svg)](https://david-dm.org/isaacs/rimraf) [![devDependency Status](https://david-dm.org/isaacs/rimraf/dev-status.svg)](https://david-dm.org/isaacs/rimraf#info=devDependencies)
+
+The [UNIX command](http://en.wikipedia.org/wiki/Rm_(Unix)) `rm -rf` for node.
 
 Install with `npm install rimraf`, or just drop rimraf.js somewhere.
 
 ## API
 
-`rimraf(f, callback)`
+`rimraf(f, [opts], callback)`
+
+The first parameter will be interpreted as a globbing pattern for files. If you
+want to disable globbing you can do so with `opts.disableGlob` (defaults to
+`false`). This might be handy, for instance, if you have filenames that contain
+globbing wildcard characters.
 
 The callback will be called with an error if there is one.  Certain
 errors are handled for you:
 
 * Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of
-  `opts.maxBusyTries` times before giving up.
+  `opts.maxBusyTries` times before giving up, adding 100ms of wait
+  between each attempt.  The default `maxBusyTries` is 3.
 * `ENOENT` - If the file doesn't exist, rimraf will return
   successfully, since your desired outcome is already the case.
+* `EMFILE` - Since `readdir` requires opening a file descriptor, it's
+  possible to hit `EMFILE` if too many file descriptors are in use.
+  In the sync case, there's nothing to be done for this.  But in the
+  async case, rimraf will gradually back off with timeouts up to
+  `opts.emfileWait` ms, which defaults to 1000.
+
+## options
+
+* unlink, chmod, stat, lstat, rmdir, readdir,
+  unlinkSync, chmodSync, statSync, lstatSync, rmdirSync, readdirSync
+
+    In order to use a custom file system library, you can override
+    specific fs functions on the options object.
+
+    If any of these functions are present on the options object, then
+    the supplied function will be used instead of the default fs
+    method.
+
+    Sync methods are only relevant for `rimraf.sync()`, of course.
+
+    For example:
+
+    ```javascript
+    var myCustomFS = require('some-custom-fs')
+
+    rimraf('some-thing', myCustomFS, callback)
+    ```
+
+* maxBusyTries
+
+    If an `EBUSY`, `ENOTEMPTY`, or `EPERM` error code is encountered
+    on Windows systems, then rimraf will retry with a linear backoff
+    wait of 100ms longer on each try.  The default maxBusyTries is 3.
+
+    Only relevant for async usage.
+
+* emfileWait
+
+    If an `EMFILE` error is encountered, then rimraf will retry
+    repeatedly with a linear backoff of 1ms longer on each try, until
+    the timeout counter hits this max.  The default limit is 1000.
+
+    If you repeatedly encounter `EMFILE` errors, then consider using
+    [graceful-fs](http://npm.im/graceful-fs) in your program.
+
+    Only relevant for async usage.
+
+* glob
+
+    Set to `false` to disable [glob](http://npm.im/glob) pattern
+    matching.
+
+    Set to an object to pass options to the glob module.  The default
+    glob options are `{ nosort: true, silent: true }`.
+
+    Glob version 6 is used in this module.
+
+    Relevant for both sync and async usage.
+
+* disableGlob
+
+    Set to any non-falsey value to disable globbing entirely.
+    (Equivalent to setting `glob: false`.)
 
 ## rimraf.sync
 
@@ -22,7 +93,7 @@ the async API.  It's better.
 ## CLI
 
 If installed with `npm install rimraf -g` it can be used as a global
-command `rimraf <path>` which is useful for cross platform support.
+command `rimraf <path> [<path> ...]` which is useful for cross platform support.
 
 ## mkdirp
 
diff --git a/bin.js b/bin.js
index 29bfa8a..1bd5a0d 100755
--- a/bin.js
+++ b/bin.js
@@ -18,7 +18,7 @@ var args = process.argv.slice(2).filter(function(arg) {
 if (help || args.length === 0) {
   // If they didn't ask for help, then this is not a "success"
   var log = help ? console.log : console.error
-  log('Usage: rimraf <path>')
+  log('Usage: rimraf <path> [<path> ...]')
   log('')
   log('  Deletes all files and folders at "path" recursively.')
   log('')
@@ -26,8 +26,15 @@ if (help || args.length === 0) {
   log('')
   log('  -h, --help    Display this usage info')
   process.exit(help ? 0 : 1)
-} else {
-  args.forEach(function(arg) {
-    rimraf.sync(arg)
+} else
+  go(0)
+
+function go (n) {
+  if (n >= args.length)
+    return
+  rimraf(args[n], function (er) {
+    if (er)
+      throw er
+    go(n+1)
   })
 }
diff --git a/package.json b/package.json
index 0cdd1c9..c2cc045 100644
--- a/package.json
+++ b/package.json
@@ -1,16 +1,26 @@
 {
   "name": "rimraf",
-  "version": "2.2.8",
+  "version": "2.5.4",
   "main": "rimraf.js",
   "description": "A deep deletion module for node (like `rm -rf`)",
   "author": "Isaac Z. Schlueter <i at izs.me> (http://blog.izs.me/)",
-  "license": {
-    "type": "MIT",
-    "url": "https://github.com/isaacs/rimraf/raw/master/LICENSE"
-  },
+  "license": "ISC",
   "repository": "git://github.com/isaacs/rimraf.git",
   "scripts": {
-    "test": "cd test && bash run.sh"
+    "test": "tap test/*.js"
+  },
+  "bin": "./bin.js",
+  "dependencies": {
+    "glob": "^7.0.5"
   },
-  "bin": "./bin.js"
+  "files": [
+    "LICENSE",
+    "README.md",
+    "bin.js",
+    "rimraf.js"
+  ],
+  "devDependencies": {
+    "mkdirp": "^0.5.1",
+    "tap": "^6.1.1"
+  }
 }
diff --git a/rimraf.js b/rimraf.js
index eb96c46..5d9a576 100644
--- a/rimraf.js
+++ b/rimraf.js
@@ -4,11 +4,15 @@ rimraf.sync = rimrafSync
 var assert = require("assert")
 var path = require("path")
 var fs = require("fs")
+var glob = require("glob")
+
+var defaultGlobOpts = {
+  nosort: true,
+  silent: true
+}
 
 // for EMFILE handling
 var timeout = 0
-exports.EMFILE_MAX = 1000
-exports.BUSYTRIES_MAX = 3
 
 var isWindows = (process.platform === "win32")
 
@@ -17,6 +21,7 @@ function defaults (options) {
     'unlink',
     'chmod',
     'stat',
+    'lstat',
     'rmdir',
     'readdir'
   ]
@@ -25,6 +30,14 @@ function defaults (options) {
     m = m + 'Sync'
     options[m] = options[m] || fs[m]
   })
+
+  options.maxBusyTries = options.maxBusyTries || 3
+  options.emfileWait = options.emfileWait || 1000
+  if (options.glob === false) {
+    options.disableGlob = true
+  }
+  options.disableGlob = options.disableGlob || false
+  options.glob = options.glob || defaultGlobOpts
 }
 
 function rimraf (p, options, cb) {
@@ -32,41 +45,72 @@ function rimraf (p, options, cb) {
     cb = options
     options = {}
   }
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
 
-  defaults(options)
+  assert(p, 'rimraf: missing path')
+  assert.equal(typeof p, 'string', 'rimraf: path should be a string')
+  assert.equal(typeof cb, 'function', 'rimraf: callback function required')
+  assert(options, 'rimraf: invalid options argument provided')
+  assert.equal(typeof options, 'object', 'rimraf: options should be object')
 
-  if (!cb) throw new Error("No callback passed to rimraf()")
+  defaults(options)
 
   var busyTries = 0
-  rimraf_(p, options, function CB (er) {
-    if (er) {
-      if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY") &&
-          busyTries < exports.BUSYTRIES_MAX) {
-        busyTries ++
-        var time = busyTries * 100
-        // try again, with the same exact callback as this one.
-        return setTimeout(function () {
-          rimraf_(p, options, CB)
-        }, time)
-      }
+  var errState = null
+  var n = 0
 
-      // this one won't happen if graceful-fs is used.
-      if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) {
-        return setTimeout(function () {
-          rimraf_(p, options, CB)
-        }, timeout ++)
-      }
+  if (options.disableGlob || !glob.hasMagic(p))
+    return afterGlob(null, [p])
 
-      // already gone
-      if (er.code === "ENOENT") er = null
-    }
+  options.lstat(p, function (er, stat) {
+    if (!er)
+      return afterGlob(null, [p])
 
-    timeout = 0
-    cb(er)
+    glob(p, options.glob, afterGlob)
   })
+
+  function next (er) {
+    errState = errState || er
+    if (--n === 0)
+      cb(errState)
+  }
+
+  function afterGlob (er, results) {
+    if (er)
+      return cb(er)
+
+    n = results.length
+    if (n === 0)
+      return cb()
+
+    results.forEach(function (p) {
+      rimraf_(p, options, function CB (er) {
+        if (er) {
+          if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
+              busyTries < options.maxBusyTries) {
+            busyTries ++
+            var time = busyTries * 100
+            // try again, with the same exact callback as this one.
+            return setTimeout(function () {
+              rimraf_(p, options, CB)
+            }, time)
+          }
+
+          // this one won't happen if graceful-fs is used.
+          if (er.code === "EMFILE" && timeout < options.emfileWait) {
+            return setTimeout(function () {
+              rimraf_(p, options, CB)
+            }, timeout ++)
+          }
+
+          // already gone
+          if (er.code === "ENOENT") er = null
+        }
+
+        timeout = 0
+        next(er)
+      })
+    })
+  }
 }
 
 // Two possible strategies.
@@ -85,18 +129,32 @@ function rimraf_ (p, options, cb) {
   assert(options)
   assert(typeof cb === 'function')
 
-  options.unlink(p, function (er) {
-    if (er) {
-      if (er.code === "ENOENT")
-        return cb(null)
-      if (er.code === "EPERM")
-        return (isWindows)
-          ? fixWinEPERM(p, options, er, cb)
-          : rmdir(p, options, er, cb)
-      if (er.code === "EISDIR")
-        return rmdir(p, options, er, cb)
-    }
-    return cb(er)
+  // sunos lets the root user unlink directories, which is... weird.
+  // so we have to lstat here and make sure it's not a dir.
+  options.lstat(p, function (er, st) {
+    if (er && er.code === "ENOENT")
+      return cb(null)
+
+    // Windows can EPERM on stat.  Life is suffering.
+    if (er && er.code === "EPERM" && isWindows)
+      fixWinEPERM(p, options, er, cb)
+
+    if (st && st.isDirectory())
+      return rmdir(p, options, er, cb)
+
+    options.unlink(p, function (er) {
+      if (er) {
+        if (er.code === "ENOENT")
+          return cb(null)
+        if (er.code === "EPERM")
+          return (isWindows)
+            ? fixWinEPERM(p, options, er, cb)
+            : rmdir(p, options, er, cb)
+        if (er.code === "EISDIR")
+          return rmdir(p, options, er, cb)
+      }
+      return cb(er)
+    })
   })
 }
 
@@ -204,19 +262,56 @@ function rimrafSync (p, options) {
   options = options || {}
   defaults(options)
 
-  assert(p)
-  assert(options)
+  assert(p, 'rimraf: missing path')
+  assert.equal(typeof p, 'string', 'rimraf: path should be a string')
+  assert(options, 'rimraf: missing options')
+  assert.equal(typeof options, 'object', 'rimraf: options should be object')
 
-  try {
-    options.unlinkSync(p)
-  } catch (er) {
-    if (er.code === "ENOENT")
-      return
-    if (er.code === "EPERM")
-      return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
-    if (er.code !== "EISDIR")
-      throw er
-    rmdirSync(p, options, er)
+  var results
+
+  if (options.disableGlob || !glob.hasMagic(p)) {
+    results = [p]
+  } else {
+    try {
+      options.lstatSync(p)
+      results = [p]
+    } catch (er) {
+      results = glob.sync(p, options.glob)
+    }
+  }
+
+  if (!results.length)
+    return
+
+  for (var i = 0; i < results.length; i++) {
+    var p = results[i]
+
+    try {
+      var st = options.lstatSync(p)
+    } catch (er) {
+      if (er.code === "ENOENT")
+        return
+
+      // Windows can EPERM on stat.  Life is suffering.
+      if (er.code === "EPERM" && isWindows)
+        fixWinEPERMSync(p, options, er)
+    }
+
+    try {
+      // sunos lets the root user unlink directories, which is... weird.
+      if (st && st.isDirectory())
+        rmdirSync(p, options, null)
+      else
+        options.unlinkSync(p)
+    } catch (er) {
+      if (er.code === "ENOENT")
+        return
+      if (er.code === "EPERM")
+        return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
+      if (er.code !== "EISDIR")
+        throw er
+      rmdirSync(p, options, er)
+    }
   }
 }
 
diff --git a/test/basic.js b/test/basic.js
new file mode 100644
index 0000000..d09885b
--- /dev/null
+++ b/test/basic.js
@@ -0,0 +1,106 @@
+var rimraf = require('../')
+var t = require('tap')
+
+var fs = require('fs')
+var fill = require('./fill.js')
+
+t.test('initial clean', function (t) {
+  rimraf.sync(__dirname + '/target')
+  t.throws(function () {
+    fs.statSync(__dirname + '/target')
+  })
+  t.end()
+})
+
+t.test('sync removal', function (t) {
+  fill()
+  t.ok(fs.statSync(__dirname + '/target').isDirectory())
+
+  rimraf.sync(__dirname + '/target')
+  t.throws(function () {
+    fs.statSync(__dirname + '/target')
+  })
+  t.end()
+})
+
+t.test('async removal', function (t) {
+  fill()
+  t.ok(fs.statSync(__dirname + '/target').isDirectory())
+
+  rimraf(__dirname + '/target', function (er) {
+    if (er)
+      throw er
+    t.throws(function () {
+      fs.statSync(__dirname + '/target')
+    })
+    t.end()
+  })
+})
+
+t.test('glob', function (t) {
+  t.plan(2)
+  t.test('async', function (t) {
+    fill()
+    var glob = require('glob')
+    var pattern = __dirname + '/target/f-*'
+    var before = glob.sync(pattern)
+    t.notEqual(before.length, 0)
+    rimraf(pattern, function (er) {
+      if (er)
+        throw er
+      var after = glob.sync(pattern)
+      t.same(after, [])
+      rimraf.sync(__dirname + '/target')
+      t.end()
+    })
+  })
+  t.test('sync', function (t) {
+    fill()
+    var glob = require('glob')
+    var pattern = __dirname + '/target/f-*'
+    var before = glob.sync(pattern)
+    t.notEqual(before.length, 0)
+    rimraf.sync(pattern)
+    var after = glob.sync(pattern)
+    t.same(after, [])
+    rimraf.sync(__dirname + '/target')
+    t.end()
+  })
+})
+
+t.test('no glob', function (t) {
+  t.plan(2)
+  t.test('async', function (t) {
+    fill()
+    var glob = require('glob')
+    var pattern = __dirname + '/target/f-*'
+    var before = glob.sync(pattern)
+    t.notEqual(before.length, 0)
+    rimraf(pattern, { disableGlob: true }, function (er) {
+      if (er)
+        throw er
+      var after = glob.sync(pattern)
+      t.same(after, before)
+      rimraf.sync(__dirname + '/target')
+      t.end()
+    })
+  })
+  t.test('sync', function (t) {
+    fill()
+    var glob = require('glob')
+    var pattern = __dirname + '/target/f-*'
+    var before = glob.sync(pattern)
+    t.notEqual(before.length, 0)
+    rimraf.sync(pattern, { disableGlob: true })
+    var after = glob.sync(pattern)
+    t.same(after, before)
+    rimraf.sync(__dirname + '/target')
+    t.end()
+  })
+})
+
+t.test('verify that cleanup happened', function (t) {
+  t.throws(fs.statSync.bind(fs, __dirname + '/../target'))
+  t.throws(fs.statSync.bind(fs, __dirname + '/target'))
+  t.end()
+})
diff --git a/test/custom-fs.js b/test/custom-fs.js
new file mode 100644
index 0000000..31674df
--- /dev/null
+++ b/test/custom-fs.js
@@ -0,0 +1,187 @@
+var rimraf = require('../')
+var fs = require('fs')
+var path = require('path')
+var t = require('tap')
+
+process.chdir(__dirname)
+
+// track that all the things happened
+var keepDirs = {}
+var intercepted = {}
+function intercept (method, path) {
+  intercepted[method] = intercepted[method] || []
+  intercepted[method].push(path)
+  intercepted[method] = intercepted[method].sort()
+  intercepted._saved = intercepted._saved.sort()
+  intercepted._removed = intercepted._removed.sort()
+}
+
+var expectAsync = {
+  _removed: [
+    'a',
+    'a/x',
+    'a/x/some-file.txt',
+    'a/y',
+    'a/y/some-file.txt',
+    'a/z',
+    'a/z/some-file.txt'
+  ],
+  _saved: [
+    'a',
+    'a/x',
+    'a/x/keep.txt',
+    'a/y',
+    'a/y/keep.txt',
+    'a/z',
+    'a/z/keep.txt'
+  ],
+  _keepDirs: { 'a/x': true, 'a/y': true, 'a/z': true, a: true, '.': true },
+  rmdir: [
+    'a',
+    'a',
+    'a/x',
+    'a/x',
+    'a/y',
+    'a/y',
+    'a/z',
+    'a/z'
+  ],
+  unlink: [
+    'a/x/keep.txt',
+    'a/x/some-file.txt',
+    'a/y/keep.txt',
+    'a/y/some-file.txt',
+    'a/z/keep.txt',
+    'a/z/some-file.txt'
+  ]
+}
+
+var expectSync = {
+  _removed: [
+    'a',
+    'a/x',
+    'a/x/some-file.txt',
+    'a/y',
+    'a/y/some-file.txt',
+    'a/z',
+    'a/z/some-file.txt'
+  ],
+  _saved: [
+    'a',
+    'a/x',
+    'a/x/keep.txt',
+    'a/y',
+    'a/y/keep.txt',
+    'a/z',
+    'a/z/keep.txt'
+  ],
+  _keepDirs: { 'a/x': true, a: true, 'a/y': true, 'a/z': true, '.': true },
+  rmdirSync: [
+    'a',
+    'a',
+    'a/x',
+    'a/x',
+    'a/y',
+    'a/y',
+    'a/z',
+    'a/z'
+  ],
+  unlinkSync: [
+    'a/x/keep.txt',
+    'a/x/some-file.txt',
+    'a/y/keep.txt',
+    'a/y/some-file.txt',
+    'a/z/keep.txt',
+    'a/z/some-file.txt'
+  ]
+}
+
+function shouldRemove (file) {
+  if (file.match(/keep.txt$/) || keepDirs[file]) {
+    // add the parent dir to keeps, to avoid ENOTEMPTY
+    intercepted._saved.push(file)
+    intercepted._saved = intercepted._saved.sort()
+    keepDirs[path.dirname(file)] = true
+    return false
+  } else {
+    intercepted._removed.push(file)
+    intercepted._removed = intercepted._removed.sort()
+    return true
+  }
+}
+
+var myFs = {
+  unlink: function (file, cb) {
+    intercept('unlink', file)
+    if (shouldRemove(file)) {
+      return fs.unlink(file, cb)
+    } else {
+      return cb()
+    }
+  },
+  unlinkSync: function (file) {
+    intercept('unlinkSync', file)
+    if (shouldRemove(file)) {
+      return fs.unlinkSync(file)
+    }
+  },
+  rmdir: function (file, cb) {
+    intercept('rmdir', file)
+    if (shouldRemove(file)) {
+      return fs.rmdir(file, cb)
+    } else {
+      return cb()
+    }
+  },
+  rmdirSync: function (file) {
+    intercept('rmdirSync', file)
+    if (shouldRemove(file)) {
+      return fs.rmdirSync(file)
+    }
+  }
+}
+
+var mkdirp = require('mkdirp')
+
+function create () {
+  intercepted = {}
+  intercepted._removed = []
+  intercepted._saved = []
+  intercepted._keepDirs = keepDirs = {}
+  mkdirp.sync('a')
+  ;['x', 'y', 'z'].forEach(function (j) {
+    mkdirp.sync('a/' + j)
+    fs.writeFileSync('a/' + j + '/some-file.txt', 'test\n')
+    fs.writeFileSync('a/' + j + '/keep.txt', 'test\n')
+  })
+}
+
+t.test('setup', function (t) {
+  create()
+  t.end()
+})
+
+t.test('rimraf with interceptor', function (t) {
+  rimraf('a', myFs, function (er) {
+    if (er) {
+      throw er
+    }
+    t.strictSame(intercepted, expectAsync)
+    create()
+    t.end()
+  })
+})
+
+t.test('rimraf sync with interceptor', function (t) {
+  create()
+  rimraf.sync('a', myFs)
+  t.strictSame(intercepted, expectSync)
+  create()
+  t.end()
+})
+
+t.test('cleanup', function (t) {
+  rimraf.sync('a')
+  t.throws(fs.statSync.bind(fs, 'a'))
+  t.end()
+})
diff --git a/test/fill.js b/test/fill.js
new file mode 100644
index 0000000..6c004d4
--- /dev/null
+++ b/test/fill.js
@@ -0,0 +1,41 @@
+var fs = require('fs')
+var mkdirp = require('mkdirp')
+
+module.exports = function () {
+  fill(4, 10, 2, __dirname + '/target')
+}
+
+if (module === require.main) {
+  require('tap').pass('yes')
+  return
+}
+
+function fill (depth, files, folders, target) {
+  mkdirp.sync(target)
+  var o = { flag: 'wx' }
+  if (process.version.match(/^v0\.8/))
+    o = 'utf8'
+
+  for (var f = files; f > 0; f--) {
+    fs.writeFileSync(target + '/f-' + depth + '-' + f, '', o)
+  }
+
+  // valid symlink
+  fs.symlinkSync('f-' + depth + '-1', target + '/link-' + depth + '-good', 'file')
+
+  // invalid symlink
+  fs.symlinkSync('does-not-exist', target + '/link-' + depth + '-bad', 'file')
+
+  // file with a name that looks like a glob
+  fs.writeFileSync(target + '/[a-z0-9].txt', '', o)
+
+  depth--
+  if (depth <= 0)
+    return
+
+  for (f = folders; f > 0; f--) {
+    mkdirp.sync(target + '/folder-' + depth + '-' + f)
+    fill(depth, files, folders, target + '/d-' + depth + '-' + f)
+  }
+}
+
diff --git a/test/run.sh b/test/run.sh
deleted file mode 100644
index 653ff9b..0000000
--- a/test/run.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-set -e
-code=0
-for i in test-*.js; do
-  echo -n $i ...
-  bash setup.sh
-  node $i
-  if [ -d target ]; then
-    echo "fail"
-    code=1
-  else
-    echo "pass"
-  fi
-done
-rm -rf target
-exit $code
diff --git a/test/setup.sh b/test/setup.sh
deleted file mode 100644
index 2602e63..0000000
--- a/test/setup.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-
-set -e
-
-files=10
-folders=2
-depth=4
-target="$PWD/target"
-
-rm -rf target
-
-fill () {
-  local depth=$1
-  local files=$2
-  local folders=$3
-  local target=$4
-
-  if ! [ -d $target ]; then
-    mkdir -p $target
-  fi
-
-  local f
-
-  f=$files
-  while [ $f -gt 0 ]; do
-    touch "$target/f-$depth-$f"
-    let f--
-  done
-
-  let depth--
-
-  if [ $depth -le 0 ]; then
-    return 0
-  fi
-
-  f=$folders
-  while [ $f -gt 0 ]; do
-    mkdir "$target/folder-$depth-$f"
-    fill $depth $files $folders "$target/d-$depth-$f"
-    let f--
-  done
-}
-
-fill $depth $files $folders $target
-
-# sanity assert
-[ -d $target ]
diff --git a/test/test-async.js b/test/test-async.js
deleted file mode 100644
index 9c2e0b7..0000000
--- a/test/test-async.js
+++ /dev/null
@@ -1,5 +0,0 @@
-var rimraf = require("../rimraf")
-  , path = require("path")
-rimraf(path.join(__dirname, "target"), function (er) {
-  if (er) throw er
-})
diff --git a/test/test-sync.js b/test/test-sync.js
deleted file mode 100644
index eb71f10..0000000
--- a/test/test-sync.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var rimraf = require("../rimraf")
-  , path = require("path")
-rimraf.sync(path.join(__dirname, "target"))

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



More information about the Pkg-javascript-commits mailing list