| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 | module.exports = rimrafrimraf.sync = rimrafSyncvar assert = require("assert")var path = require("path")var fs = require("fs")var glob = undefinedtry {  glob = require("glob")} catch (_err) {  // treat glob as optional.}var _0666 = parseInt('666', 8)var defaultGlobOpts = {  nosort: true,  silent: true}// for EMFILE handlingvar timeout = 0var isWindows = (process.platform === "win32")function defaults (options) {  var methods = [    'unlink',    'chmod',    'stat',    'lstat',    'rmdir',    'readdir'  ]  methods.forEach(function(m) {    options[m] = options[m] || fs[m]    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  }  if (options.disableGlob !== true && glob === undefined) {    throw Error('glob dependency not found, set `options.disableGlob = true` if intentional')  }  options.disableGlob = options.disableGlob || false  options.glob = options.glob || defaultGlobOpts}function rimraf (p, options, cb) {  if (typeof options === 'function') {    cb = options    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')  defaults(options)  var busyTries = 0  var errState = null  var n = 0  if (options.disableGlob || !glob.hasMagic(p))    return afterGlob(null, [p])  options.lstat(p, function (er, stat) {    if (!er)      return afterGlob(null, [p])    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 ((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.// 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')  // 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)    })  })}function fixWinEPERM (p, options, er, cb) {  assert(p)  assert(options)  assert(typeof cb === 'function')  if (er)    assert(er instanceof Error)  options.chmod(p, _0666, 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, _0666)  } 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, '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')  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)    }  }}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)  })  // We only end up here once we got ENOTEMPTY at least once, and  // at this point, we are guaranteed to have removed all the kids.  // So, we know that it won't be ENOENT or ENOTDIR or anything else.  // try really hard to delete stuff on windows, because it has a  // PROFOUNDLY annoying habit of not closing handles promptly when  // files are deleted, resulting in spurious ENOTEMPTY errors.  var retries = isWindows ? 100 : 1  var i = 0  do {    var threw = true    try {      var ret = options.rmdirSync(p, options)      threw = false      return ret    } finally {      if (++i < retries && threw)        continue    }  } while (true)}
 |