diff options
Diffstat (limited to 'node_modules/rimraf/fiber.js')
-rw-r--r-- | node_modules/rimraf/fiber.js | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/node_modules/rimraf/fiber.js b/node_modules/rimraf/fiber.js new file mode 100644 index 000000000..8812a6b44 --- /dev/null +++ b/node_modules/rimraf/fiber.js @@ -0,0 +1,86 @@ +// fiber/future port originally written by Marcel Laverdet +// https://gist.github.com/1131093 +// I updated it to bring to feature parity with cb version. +// The bugs are probably mine, not Marcel's. +// -- isaacs + +var path = require('path') + , fs = require('fs') + , Future = require('fibers/future') + +// Create future-returning fs functions +var fs2 = {} +for (var ii in fs) { + fs2[ii] = Future.wrap(fs[ii]) +} + +// Return a future which just pauses for a certain amount of time + +function timer (ms) { + var future = new Future + setTimeout(function () { + future.return() + }, ms) + return future +} + +function realish (p) { + return path.resolve(path.dirname(fs2.readlink(p))) +} + +// for EMFILE backoff. +var timeout = 0 + , EMFILE_MAX = 1000 + +function rimraf_ (p, opts) { + opts = opts || {} + opts.maxBusyTries = opts.maxBusyTries || 3 + if (opts.gently) opts.gently = path.resolve(opts.gently) + var busyTries = 0 + + // exits by throwing or returning. + // loops on handled errors. + while (true) { + try { + var stat = fs2.lstat(p).wait() + + // check to make sure that symlinks are ours. + if (opts.gently) { + var rp = stat.isSymbolicLink() ? realish(p) : path.resolve(p) + if (rp.indexOf(opts.gently) !== 0) { + var er = new Error("Refusing to delete: "+p+" not in "+opts.gently) + er.errno = require("constants").EEXIST + er.code = "EEXIST" + er.path = p + throw er + } + } + + if (!stat.isDirectory()) return fs2.unlink(p).wait() + + var rimrafs = fs2.readdir(p).wait().map(function (file) { + return rimraf(path.join(p, file), opts) + }) + + Future.wait(rimrafs) + fs2.rmdir(p).wait() + timeout = 0 + return + + } catch (er) { + if (er.message.match(/^EMFILE/) && timeout < EMFILE_MAX) { + timer(timeout++).wait() + } else if (er.message.match(/^EBUSY/) + && busyTries < opt.maxBusyTries) { + timer(++busyTries * 100).wait() + } else if (er.message.match(/^ENOENT/)) { + // already gone + return + } else { + throw er + } + } + } +} + +var rimraf = module.exports = rimraf_.future() |