You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

86 lines
2.1 KiB

// 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()