| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 | module.exports = rimrafrimraf.sync = rimrafSyncvar assert = require("assert")var path = require("path")var fs = require("fs")// for EMFILE handlingvar timeout = 0exports.EMFILE_MAX = 1000exports.BUSYTRIES_MAX = 3var isWindows = (process.platform === "win32")function defaults (options) {  var methods = [    'unlink',    'chmod',    'stat',    'rmdir',    'readdir'  ]  methods.forEach(function(m) {    options[m] = options[m] || fs[m]    m = m + 'Sync'    options[m] = options[m] || fs[m]  })}function rimraf (p, options, cb) {  if (typeof options === 'function') {    cb = options    options = {}  }  assert(p)  assert(options)  assert(typeof cb === 'function')  defaults(options)  if (!cb) throw new Error("No callback passed to rimraf()")  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)      }      // 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 ++)      }      // already gone      if (er.code === "ENOENT") er = null    }    timeout = 0    cb(er)  })}// Two possible strategies.// 1. Assume it's a file.  unlink it, then do the dir stuff on EPERM or EISDIR// 2. Assume it's a directory.  readdir, then do the file stuff on ENOTDIR//// Both result in an extra syscall when you guess wrong.  However, there// are likely far more normal files in the world than directories.  This// is based on the assumption that a the average number of files per// directory is >= 1.//// If anyone ever complains about this, then I guess the strategy could// be made configurable somehow.  But until then, YAGNI.function rimraf_ (p, options, cb) {  assert(p)  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)  })}function fixWinEPERM (p, options, er, cb) {  assert(p)  assert(options)  assert(typeof cb === 'function')  if (er)    assert(er instanceof Error)  options.chmod(p, 666, function (er2) {    if (er2)      cb(er2.code === "ENOENT" ? null : er)    else      options.stat(p, function(er3, stats) {        if (er3)          cb(er3.code === "ENOENT" ? null : er)        else if (stats.isDirectory())          rmdir(p, options, er, cb)        else          options.unlink(p, cb)      })  })}function fixWinEPERMSync (p, options, er) {  assert(p)  assert(options)  if (er)    assert(er instanceof Error)  try {    options.chmodSync(p, 666)  } catch (er2) {    if (er2.code === "ENOENT")      return    else      throw er  }  try {    var stats = options.statSync(p)  } catch (er3) {    if (er3.code === "ENOENT")      return    else      throw er  }  if (stats.isDirectory())    rmdirSync(p, options, er)  else    options.unlinkSync(p)}function rmdir (p, options, originalEr, cb) {  assert(p)  assert(options)  if (originalEr)    assert(originalEr instanceof Error)  assert(typeof cb === 'function')  // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)  // if we guessed wrong, and it's not a directory, then  // raise the original error.  options.rmdir(p, function (er) {    if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))      rmkids(p, options, cb)    else if (er && er.code === "ENOTDIR")      cb(originalEr)    else      cb(er)  })}function rmkids(p, options, cb) {  assert(p)  assert(options)  assert(typeof cb === 'function')  options.readdir(p, function (er, files) {    if (er)      return cb(er)    var n = files.length    if (n === 0)      return options.rmdir(p, cb)    var errState    files.forEach(function (f) {      rimraf(path.join(p, f), options, function (er) {        if (errState)          return        if (er)          return cb(errState = er)        if (--n === 0)          options.rmdir(p, cb)      })    })  })}// this looks simpler, and is strictly *faster*, but will// tie up the JavaScript thread and fail on excessively// deep directory trees.function rimrafSync (p, options) {  options = options || {}  defaults(options)  assert(p)  assert(options)  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)  }}function rmdirSync (p, options, originalEr) {  assert(p)  assert(options)  if (originalEr)    assert(originalEr instanceof Error)  try {    options.rmdirSync(p)  } catch (er) {    if (er.code === "ENOENT")      return    if (er.code === "ENOTDIR")      throw originalEr    if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")      rmkidsSync(p, options)  }}function rmkidsSync (p, options) {  assert(p)  assert(options)  options.readdirSync(p).forEach(function (f) {    rimrafSync(path.join(p, f), options)  })  options.rmdirSync(p, options)}
 |