"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/rimraf/rimraf.js" (8 Mar 2017, 8959 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 module.exports = rimraf
    2 rimraf.sync = rimrafSync
    3 
    4 var assert = require("assert")
    5 var path = require("path")
    6 var fs = require("fs")
    7 var glob = require("glob")
    8 
    9 var defaultGlobOpts = {
   10   nosort: true,
   11   silent: true
   12 }
   13 
   14 // for EMFILE handling
   15 var timeout = 0
   16 
   17 var isWindows = (process.platform === "win32")
   18 
   19 function defaults (options) {
   20   var methods = [
   21     'unlink',
   22     'chmod',
   23     'stat',
   24     'lstat',
   25     'rmdir',
   26     'readdir'
   27   ]
   28   methods.forEach(function(m) {
   29     options[m] = options[m] || fs[m]
   30     m = m + 'Sync'
   31     options[m] = options[m] || fs[m]
   32   })
   33 
   34   options.maxBusyTries = options.maxBusyTries || 3
   35   options.emfileWait = options.emfileWait || 1000
   36   if (options.glob === false) {
   37     options.disableGlob = true
   38   }
   39   options.disableGlob = options.disableGlob || false
   40   options.glob = options.glob || defaultGlobOpts
   41 }
   42 
   43 function rimraf (p, options, cb) {
   44   if (typeof options === 'function') {
   45     cb = options
   46     options = {}
   47   }
   48 
   49   assert(p, 'rimraf: missing path')
   50   assert.equal(typeof p, 'string', 'rimraf: path should be a string')
   51   assert.equal(typeof cb, 'function', 'rimraf: callback function required')
   52   assert(options, 'rimraf: invalid options argument provided')
   53   assert.equal(typeof options, 'object', 'rimraf: options should be object')
   54 
   55   defaults(options)
   56 
   57   var busyTries = 0
   58   var errState = null
   59   var n = 0
   60 
   61   if (options.disableGlob || !glob.hasMagic(p))
   62     return afterGlob(null, [p])
   63 
   64   options.lstat(p, function (er, stat) {
   65     if (!er)
   66       return afterGlob(null, [p])
   67 
   68     glob(p, options.glob, afterGlob)
   69   })
   70 
   71   function next (er) {
   72     errState = errState || er
   73     if (--n === 0)
   74       cb(errState)
   75   }
   76 
   77   function afterGlob (er, results) {
   78     if (er)
   79       return cb(er)
   80 
   81     n = results.length
   82     if (n === 0)
   83       return cb()
   84 
   85     results.forEach(function (p) {
   86       rimraf_(p, options, function CB (er) {
   87         if (er) {
   88           if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
   89               busyTries < options.maxBusyTries) {
   90             busyTries ++
   91             var time = busyTries * 100
   92             // try again, with the same exact callback as this one.
   93             return setTimeout(function () {
   94               rimraf_(p, options, CB)
   95             }, time)
   96           }
   97 
   98           // this one won't happen if graceful-fs is used.
   99           if (er.code === "EMFILE" && timeout < options.emfileWait) {
  100             return setTimeout(function () {
  101               rimraf_(p, options, CB)
  102             }, timeout ++)
  103           }
  104 
  105           // already gone
  106           if (er.code === "ENOENT") er = null
  107         }
  108 
  109         timeout = 0
  110         next(er)
  111       })
  112     })
  113   }
  114 }
  115 
  116 // Two possible strategies.
  117 // 1. Assume it's a file.  unlink it, then do the dir stuff on EPERM or EISDIR
  118 // 2. Assume it's a directory.  readdir, then do the file stuff on ENOTDIR
  119 //
  120 // Both result in an extra syscall when you guess wrong.  However, there
  121 // are likely far more normal files in the world than directories.  This
  122 // is based on the assumption that a the average number of files per
  123 // directory is >= 1.
  124 //
  125 // If anyone ever complains about this, then I guess the strategy could
  126 // be made configurable somehow.  But until then, YAGNI.
  127 function rimraf_ (p, options, cb) {
  128   assert(p)
  129   assert(options)
  130   assert(typeof cb === 'function')
  131 
  132   // sunos lets the root user unlink directories, which is... weird.
  133   // so we have to lstat here and make sure it's not a dir.
  134   options.lstat(p, function (er, st) {
  135     if (er && er.code === "ENOENT")
  136       return cb(null)
  137 
  138     // Windows can EPERM on stat.  Life is suffering.
  139     if (er && er.code === "EPERM" && isWindows)
  140       fixWinEPERM(p, options, er, cb)
  141 
  142     if (st && st.isDirectory())
  143       return rmdir(p, options, er, cb)
  144 
  145     options.unlink(p, function (er) {
  146       if (er) {
  147         if (er.code === "ENOENT")
  148           return cb(null)
  149         if (er.code === "EPERM")
  150           return (isWindows)
  151             ? fixWinEPERM(p, options, er, cb)
  152             : rmdir(p, options, er, cb)
  153         if (er.code === "EISDIR")
  154           return rmdir(p, options, er, cb)
  155       }
  156       return cb(er)
  157     })
  158   })
  159 }
  160 
  161 function fixWinEPERM (p, options, er, cb) {
  162   assert(p)
  163   assert(options)
  164   assert(typeof cb === 'function')
  165   if (er)
  166     assert(er instanceof Error)
  167 
  168   options.chmod(p, 666, function (er2) {
  169     if (er2)
  170       cb(er2.code === "ENOENT" ? null : er)
  171     else
  172       options.stat(p, function(er3, stats) {
  173         if (er3)
  174           cb(er3.code === "ENOENT" ? null : er)
  175         else if (stats.isDirectory())
  176           rmdir(p, options, er, cb)
  177         else
  178           options.unlink(p, cb)
  179       })
  180   })
  181 }
  182 
  183 function fixWinEPERMSync (p, options, er) {
  184   assert(p)
  185   assert(options)
  186   if (er)
  187     assert(er instanceof Error)
  188 
  189   try {
  190     options.chmodSync(p, 666)
  191   } catch (er2) {
  192     if (er2.code === "ENOENT")
  193       return
  194     else
  195       throw er
  196   }
  197 
  198   try {
  199     var stats = options.statSync(p)
  200   } catch (er3) {
  201     if (er3.code === "ENOENT")
  202       return
  203     else
  204       throw er
  205   }
  206 
  207   if (stats.isDirectory())
  208     rmdirSync(p, options, er)
  209   else
  210     options.unlinkSync(p)
  211 }
  212 
  213 function rmdir (p, options, originalEr, cb) {
  214   assert(p)
  215   assert(options)
  216   if (originalEr)
  217     assert(originalEr instanceof Error)
  218   assert(typeof cb === 'function')
  219 
  220   // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
  221   // if we guessed wrong, and it's not a directory, then
  222   // raise the original error.
  223   options.rmdir(p, function (er) {
  224     if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))
  225       rmkids(p, options, cb)
  226     else if (er && er.code === "ENOTDIR")
  227       cb(originalEr)
  228     else
  229       cb(er)
  230   })
  231 }
  232 
  233 function rmkids(p, options, cb) {
  234   assert(p)
  235   assert(options)
  236   assert(typeof cb === 'function')
  237 
  238   options.readdir(p, function (er, files) {
  239     if (er)
  240       return cb(er)
  241     var n = files.length
  242     if (n === 0)
  243       return options.rmdir(p, cb)
  244     var errState
  245     files.forEach(function (f) {
  246       rimraf(path.join(p, f), options, function (er) {
  247         if (errState)
  248           return
  249         if (er)
  250           return cb(errState = er)
  251         if (--n === 0)
  252           options.rmdir(p, cb)
  253       })
  254     })
  255   })
  256 }
  257 
  258 // this looks simpler, and is strictly *faster*, but will
  259 // tie up the JavaScript thread and fail on excessively
  260 // deep directory trees.
  261 function rimrafSync (p, options) {
  262   options = options || {}
  263   defaults(options)
  264 
  265   assert(p, 'rimraf: missing path')
  266   assert.equal(typeof p, 'string', 'rimraf: path should be a string')
  267   assert(options, 'rimraf: missing options')
  268   assert.equal(typeof options, 'object', 'rimraf: options should be object')
  269 
  270   var results
  271 
  272   if (options.disableGlob || !glob.hasMagic(p)) {
  273     results = [p]
  274   } else {
  275     try {
  276       options.lstatSync(p)
  277       results = [p]
  278     } catch (er) {
  279       results = glob.sync(p, options.glob)
  280     }
  281   }
  282 
  283   if (!results.length)
  284     return
  285 
  286   for (var i = 0; i < results.length; i++) {
  287     var p = results[i]
  288 
  289     try {
  290       var st = options.lstatSync(p)
  291     } catch (er) {
  292       if (er.code === "ENOENT")
  293         return
  294 
  295       // Windows can EPERM on stat.  Life is suffering.
  296       if (er.code === "EPERM" && isWindows)
  297         fixWinEPERMSync(p, options, er)
  298     }
  299 
  300     try {
  301       // sunos lets the root user unlink directories, which is... weird.
  302       if (st && st.isDirectory())
  303         rmdirSync(p, options, null)
  304       else
  305         options.unlinkSync(p)
  306     } catch (er) {
  307       if (er.code === "ENOENT")
  308         return
  309       if (er.code === "EPERM")
  310         return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
  311       if (er.code !== "EISDIR")
  312         throw er
  313 
  314       rmdirSync(p, options, er)
  315     }
  316   }
  317 }
  318 
  319 function rmdirSync (p, options, originalEr) {
  320   assert(p)
  321   assert(options)
  322   if (originalEr)
  323     assert(originalEr instanceof Error)
  324 
  325   try {
  326     options.rmdirSync(p)
  327   } catch (er) {
  328     if (er.code === "ENOENT")
  329       return
  330     if (er.code === "ENOTDIR")
  331       throw originalEr
  332     if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")
  333       rmkidsSync(p, options)
  334   }
  335 }
  336 
  337 function rmkidsSync (p, options) {
  338   assert(p)
  339   assert(options)
  340   options.readdirSync(p).forEach(function (f) {
  341     rimrafSync(path.join(p, f), options)
  342   })
  343 
  344   // We only end up here once we got ENOTEMPTY at least once, and
  345   // at this point, we are guaranteed to have removed all the kids.
  346   // So, we know that it won't be ENOENT or ENOTDIR or anything else.
  347   // try really hard to delete stuff on windows, because it has a
  348   // PROFOUNDLY annoying habit of not closing handles promptly when
  349   // files are deleted, resulting in spurious ENOTEMPTY errors.
  350   var retries = isWindows ? 100 : 1
  351   var i = 0
  352   do {
  353     var threw = true
  354     try {
  355       var ret = options.rmdirSync(p, options)
  356       threw = false
  357       return ret
  358     } finally {
  359       if (++i < retries && threw)
  360         continue
  361     }
  362   } while (true)
  363 }