údržba
This commit is contained in:
		
							
								
								
									
										65
									
								
								CyLukTs/lukan/node_modules/rimraf/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								CyLukTs/lukan/node_modules/rimraf/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
# v3.0
 | 
			
		||||
 | 
			
		||||
- Add `--preserve-root` option to executable (default true)
 | 
			
		||||
- Drop support for Node.js below version 6
 | 
			
		||||
 | 
			
		||||
# v2.7
 | 
			
		||||
 | 
			
		||||
- Make `glob` an optional dependency
 | 
			
		||||
 | 
			
		||||
# 2.6
 | 
			
		||||
 | 
			
		||||
- Retry on EBUSY on non-windows platforms as well
 | 
			
		||||
- Make `rimraf.sync` 10000% more reliable on Windows
 | 
			
		||||
 | 
			
		||||
# 2.5
 | 
			
		||||
 | 
			
		||||
- Handle Windows EPERM when lstat-ing read-only dirs
 | 
			
		||||
- Add glob option to pass options to glob
 | 
			
		||||
 | 
			
		||||
# 2.4
 | 
			
		||||
 | 
			
		||||
- Add EPERM to delay/retry loop
 | 
			
		||||
- Add `disableGlob` option
 | 
			
		||||
 | 
			
		||||
# 2.3
 | 
			
		||||
 | 
			
		||||
- Make maxBusyTries and emfileWait configurable
 | 
			
		||||
- Handle weird SunOS unlink-dir issue
 | 
			
		||||
- Glob the CLI arg for better Windows support
 | 
			
		||||
 | 
			
		||||
# 2.2
 | 
			
		||||
 | 
			
		||||
- Handle ENOENT properly on Windows
 | 
			
		||||
- Allow overriding fs methods
 | 
			
		||||
- Treat EPERM as indicative of non-empty dir
 | 
			
		||||
- Remove optional graceful-fs dep
 | 
			
		||||
- Consistently return null error instead of undefined on success
 | 
			
		||||
- win32: Treat ENOTEMPTY the same as EBUSY
 | 
			
		||||
- Add `rimraf` binary
 | 
			
		||||
 | 
			
		||||
# 2.1
 | 
			
		||||
 | 
			
		||||
- Fix SunOS error code for a non-empty directory
 | 
			
		||||
- Try rmdir before readdir
 | 
			
		||||
- Treat EISDIR like EPERM
 | 
			
		||||
- Remove chmod
 | 
			
		||||
- Remove lstat polyfill, node 0.7 is not supported
 | 
			
		||||
 | 
			
		||||
# 2.0
 | 
			
		||||
 | 
			
		||||
- Fix myGid call to check process.getgid
 | 
			
		||||
- Simplify the EBUSY backoff logic.
 | 
			
		||||
- Use fs.lstat in node >= 0.7.9
 | 
			
		||||
- Remove gently option
 | 
			
		||||
- remove fiber implementation
 | 
			
		||||
- Delete files that are marked read-only
 | 
			
		||||
 | 
			
		||||
# 1.0
 | 
			
		||||
 | 
			
		||||
- Allow ENOENT in sync method
 | 
			
		||||
- Throw when no callback is provided
 | 
			
		||||
- Make opts.gently an absolute path
 | 
			
		||||
- use 'stat' if 'lstat' is not available
 | 
			
		||||
- Consistent error naming, and rethrow non-ENOENT stat errors
 | 
			
		||||
- add fiber implementation
 | 
			
		||||
							
								
								
									
										15
									
								
								CyLukTs/lukan/node_modules/rimraf/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								CyLukTs/lukan/node_modules/rimraf/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
The ISC License
 | 
			
		||||
 | 
			
		||||
Copyright (c) Isaac Z. Schlueter and Contributors
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and/or distribute this software for any
 | 
			
		||||
purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 | 
			
		||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
							
								
								
									
										101
									
								
								CyLukTs/lukan/node_modules/rimraf/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								CyLukTs/lukan/node_modules/rimraf/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
[](https://travis-ci.org/isaacs/rimraf) [](https://david-dm.org/isaacs/rimraf) [](https://david-dm.org/isaacs/rimraf#info=devDependencies)
 | 
			
		||||
 | 
			
		||||
The [UNIX command](http://en.wikipedia.org/wiki/Rm_(Unix)) `rm -rf` for node.
 | 
			
		||||
 | 
			
		||||
Install with `npm install rimraf`, or just drop rimraf.js somewhere.
 | 
			
		||||
 | 
			
		||||
## API
 | 
			
		||||
 | 
			
		||||
`rimraf(f, [opts], callback)`
 | 
			
		||||
 | 
			
		||||
The first parameter will be interpreted as a globbing pattern for files. If you
 | 
			
		||||
want to disable globbing you can do so with `opts.disableGlob` (defaults to
 | 
			
		||||
`false`). This might be handy, for instance, if you have filenames that contain
 | 
			
		||||
globbing wildcard characters.
 | 
			
		||||
 | 
			
		||||
The callback will be called with an error if there is one.  Certain
 | 
			
		||||
errors are handled for you:
 | 
			
		||||
 | 
			
		||||
* Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of
 | 
			
		||||
  `opts.maxBusyTries` times before giving up, adding 100ms of wait
 | 
			
		||||
  between each attempt.  The default `maxBusyTries` is 3.
 | 
			
		||||
* `ENOENT` - If the file doesn't exist, rimraf will return
 | 
			
		||||
  successfully, since your desired outcome is already the case.
 | 
			
		||||
* `EMFILE` - Since `readdir` requires opening a file descriptor, it's
 | 
			
		||||
  possible to hit `EMFILE` if too many file descriptors are in use.
 | 
			
		||||
  In the sync case, there's nothing to be done for this.  But in the
 | 
			
		||||
  async case, rimraf will gradually back off with timeouts up to
 | 
			
		||||
  `opts.emfileWait` ms, which defaults to 1000.
 | 
			
		||||
 | 
			
		||||
## options
 | 
			
		||||
 | 
			
		||||
* unlink, chmod, stat, lstat, rmdir, readdir,
 | 
			
		||||
  unlinkSync, chmodSync, statSync, lstatSync, rmdirSync, readdirSync
 | 
			
		||||
 | 
			
		||||
    In order to use a custom file system library, you can override
 | 
			
		||||
    specific fs functions on the options object.
 | 
			
		||||
 | 
			
		||||
    If any of these functions are present on the options object, then
 | 
			
		||||
    the supplied function will be used instead of the default fs
 | 
			
		||||
    method.
 | 
			
		||||
 | 
			
		||||
    Sync methods are only relevant for `rimraf.sync()`, of course.
 | 
			
		||||
 | 
			
		||||
    For example:
 | 
			
		||||
 | 
			
		||||
    ```javascript
 | 
			
		||||
    var myCustomFS = require('some-custom-fs')
 | 
			
		||||
 | 
			
		||||
    rimraf('some-thing', myCustomFS, callback)
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
* maxBusyTries
 | 
			
		||||
 | 
			
		||||
    If an `EBUSY`, `ENOTEMPTY`, or `EPERM` error code is encountered
 | 
			
		||||
    on Windows systems, then rimraf will retry with a linear backoff
 | 
			
		||||
    wait of 100ms longer on each try.  The default maxBusyTries is 3.
 | 
			
		||||
 | 
			
		||||
    Only relevant for async usage.
 | 
			
		||||
 | 
			
		||||
* emfileWait
 | 
			
		||||
 | 
			
		||||
    If an `EMFILE` error is encountered, then rimraf will retry
 | 
			
		||||
    repeatedly with a linear backoff of 1ms longer on each try, until
 | 
			
		||||
    the timeout counter hits this max.  The default limit is 1000.
 | 
			
		||||
 | 
			
		||||
    If you repeatedly encounter `EMFILE` errors, then consider using
 | 
			
		||||
    [graceful-fs](http://npm.im/graceful-fs) in your program.
 | 
			
		||||
 | 
			
		||||
    Only relevant for async usage.
 | 
			
		||||
 | 
			
		||||
* glob
 | 
			
		||||
 | 
			
		||||
    Set to `false` to disable [glob](http://npm.im/glob) pattern
 | 
			
		||||
    matching.
 | 
			
		||||
 | 
			
		||||
    Set to an object to pass options to the glob module.  The default
 | 
			
		||||
    glob options are `{ nosort: true, silent: true }`.
 | 
			
		||||
 | 
			
		||||
    Glob version 6 is used in this module.
 | 
			
		||||
 | 
			
		||||
    Relevant for both sync and async usage.
 | 
			
		||||
 | 
			
		||||
* disableGlob
 | 
			
		||||
 | 
			
		||||
    Set to any non-falsey value to disable globbing entirely.
 | 
			
		||||
    (Equivalent to setting `glob: false`.)
 | 
			
		||||
 | 
			
		||||
## rimraf.sync
 | 
			
		||||
 | 
			
		||||
It can remove stuff synchronously, too.  But that's not so good.  Use
 | 
			
		||||
the async API.  It's better.
 | 
			
		||||
 | 
			
		||||
## CLI
 | 
			
		||||
 | 
			
		||||
If installed with `npm install rimraf -g` it can be used as a global
 | 
			
		||||
command `rimraf <path> [<path> ...]` which is useful for cross platform support.
 | 
			
		||||
 | 
			
		||||
## mkdirp
 | 
			
		||||
 | 
			
		||||
If you need to create a directory recursively, check out
 | 
			
		||||
[mkdirp](https://github.com/substack/node-mkdirp).
 | 
			
		||||
							
								
								
									
										68
									
								
								CyLukTs/lukan/node_modules/rimraf/bin.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								CyLukTs/lukan/node_modules/rimraf/bin.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
#!/usr/bin/env node
 | 
			
		||||
 | 
			
		||||
const rimraf = require('./')
 | 
			
		||||
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
const isRoot = arg => /^(\/|[a-zA-Z]:\\)$/.test(path.resolve(arg))
 | 
			
		||||
const filterOutRoot = arg => {
 | 
			
		||||
  const ok = preserveRoot === false || !isRoot(arg)
 | 
			
		||||
  if (!ok) {
 | 
			
		||||
    console.error(`refusing to remove ${arg}`)
 | 
			
		||||
    console.error('Set --no-preserve-root to allow this')
 | 
			
		||||
  }
 | 
			
		||||
  return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let help = false
 | 
			
		||||
let dashdash = false
 | 
			
		||||
let noglob = false
 | 
			
		||||
let preserveRoot = true
 | 
			
		||||
const args = process.argv.slice(2).filter(arg => {
 | 
			
		||||
  if (dashdash)
 | 
			
		||||
    return !!arg
 | 
			
		||||
  else if (arg === '--')
 | 
			
		||||
    dashdash = true
 | 
			
		||||
  else if (arg === '--no-glob' || arg === '-G')
 | 
			
		||||
    noglob = true
 | 
			
		||||
  else if (arg === '--glob' || arg === '-g')
 | 
			
		||||
    noglob = false
 | 
			
		||||
  else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/))
 | 
			
		||||
    help = true
 | 
			
		||||
  else if (arg === '--preserve-root')
 | 
			
		||||
    preserveRoot = true
 | 
			
		||||
  else if (arg === '--no-preserve-root')
 | 
			
		||||
    preserveRoot = false
 | 
			
		||||
  else
 | 
			
		||||
    return !!arg
 | 
			
		||||
}).filter(arg => !preserveRoot || filterOutRoot(arg))
 | 
			
		||||
 | 
			
		||||
const go = n => {
 | 
			
		||||
  if (n >= args.length)
 | 
			
		||||
    return
 | 
			
		||||
  const options = noglob ? { glob: false } : {}
 | 
			
		||||
  rimraf(args[n], options, er => {
 | 
			
		||||
    if (er)
 | 
			
		||||
      throw er
 | 
			
		||||
    go(n+1)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (help || args.length === 0) {
 | 
			
		||||
  // If they didn't ask for help, then this is not a "success"
 | 
			
		||||
  const log = help ? console.log : console.error
 | 
			
		||||
  log('Usage: rimraf <path> [<path> ...]')
 | 
			
		||||
  log('')
 | 
			
		||||
  log('  Deletes all files and folders at "path" recursively.')
 | 
			
		||||
  log('')
 | 
			
		||||
  log('Options:')
 | 
			
		||||
  log('')
 | 
			
		||||
  log('  -h, --help          Display this usage info')
 | 
			
		||||
  log('  -G, --no-glob       Do not expand glob patterns in arguments')
 | 
			
		||||
  log('  -g, --glob          Expand glob patterns in arguments (default)')
 | 
			
		||||
  log('  --preserve-root     Do not remove \'/\' (default)')
 | 
			
		||||
  log('  --no-preserve-root  Do not treat \'/\' specially')
 | 
			
		||||
  log('  --                  Stop parsing flags')
 | 
			
		||||
  process.exit(help ? 0 : 1)
 | 
			
		||||
} else
 | 
			
		||||
  go(0)
 | 
			
		||||
							
								
								
									
										32
									
								
								CyLukTs/lukan/node_modules/rimraf/package.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								CyLukTs/lukan/node_modules/rimraf/package.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "rimraf",
 | 
			
		||||
  "version": "3.0.2",
 | 
			
		||||
  "main": "rimraf.js",
 | 
			
		||||
  "description": "A deep deletion module for node (like `rm -rf`)",
 | 
			
		||||
  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "repository": "git://github.com/isaacs/rimraf.git",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "preversion": "npm test",
 | 
			
		||||
    "postversion": "npm publish",
 | 
			
		||||
    "postpublish": "git push origin --follow-tags",
 | 
			
		||||
    "test": "tap test/*.js"
 | 
			
		||||
  },
 | 
			
		||||
  "bin": "./bin.js",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "glob": "^7.1.3"
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "LICENSE",
 | 
			
		||||
    "README.md",
 | 
			
		||||
    "bin.js",
 | 
			
		||||
    "rimraf.js"
 | 
			
		||||
  ],
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "mkdirp": "^0.5.1",
 | 
			
		||||
    "tap": "^12.1.1"
 | 
			
		||||
  },
 | 
			
		||||
  "funding": {
 | 
			
		||||
    "url": "https://github.com/sponsors/isaacs"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										360
									
								
								CyLukTs/lukan/node_modules/rimraf/rimraf.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								CyLukTs/lukan/node_modules/rimraf/rimraf.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,360 @@
 | 
			
		||||
const assert = require("assert")
 | 
			
		||||
const path = require("path")
 | 
			
		||||
const fs = require("fs")
 | 
			
		||||
let glob = undefined
 | 
			
		||||
try {
 | 
			
		||||
  glob = require("glob")
 | 
			
		||||
} catch (_err) {
 | 
			
		||||
  // treat glob as optional.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const defaultGlobOpts = {
 | 
			
		||||
  nosort: true,
 | 
			
		||||
  silent: true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// for EMFILE handling
 | 
			
		||||
let timeout = 0
 | 
			
		||||
 | 
			
		||||
const isWindows = (process.platform === "win32")
 | 
			
		||||
 | 
			
		||||
const defaults = options => {
 | 
			
		||||
  const methods = [
 | 
			
		||||
    'unlink',
 | 
			
		||||
    'chmod',
 | 
			
		||||
    'stat',
 | 
			
		||||
    'lstat',
 | 
			
		||||
    'rmdir',
 | 
			
		||||
    'readdir'
 | 
			
		||||
  ]
 | 
			
		||||
  methods.forEach(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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const 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)
 | 
			
		||||
 | 
			
		||||
  let busyTries = 0
 | 
			
		||||
  let errState = null
 | 
			
		||||
  let n = 0
 | 
			
		||||
 | 
			
		||||
  const next = (er) => {
 | 
			
		||||
    errState = errState || er
 | 
			
		||||
    if (--n === 0)
 | 
			
		||||
      cb(errState)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const afterGlob = (er, results) => {
 | 
			
		||||
    if (er)
 | 
			
		||||
      return cb(er)
 | 
			
		||||
 | 
			
		||||
    n = results.length
 | 
			
		||||
    if (n === 0)
 | 
			
		||||
      return cb()
 | 
			
		||||
 | 
			
		||||
    results.forEach(p => {
 | 
			
		||||
      const CB = (er) => {
 | 
			
		||||
        if (er) {
 | 
			
		||||
          if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
 | 
			
		||||
              busyTries < options.maxBusyTries) {
 | 
			
		||||
            busyTries ++
 | 
			
		||||
            // try again, with the same exact callback as this one.
 | 
			
		||||
            return setTimeout(() => rimraf_(p, options, CB), busyTries * 100)
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // this one won't happen if graceful-fs is used.
 | 
			
		||||
          if (er.code === "EMFILE" && timeout < options.emfileWait) {
 | 
			
		||||
            return setTimeout(() => rimraf_(p, options, CB), timeout ++)
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // already gone
 | 
			
		||||
          if (er.code === "ENOENT") er = null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        timeout = 0
 | 
			
		||||
        next(er)
 | 
			
		||||
      }
 | 
			
		||||
      rimraf_(p, options, CB)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (options.disableGlob || !glob.hasMagic(p))
 | 
			
		||||
    return afterGlob(null, [p])
 | 
			
		||||
 | 
			
		||||
  options.lstat(p, (er, stat) => {
 | 
			
		||||
    if (!er)
 | 
			
		||||
      return afterGlob(null, [p])
 | 
			
		||||
 | 
			
		||||
    glob(p, options.glob, afterGlob)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
const 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, (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, 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)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const fixWinEPERM = (p, options, er, cb) => {
 | 
			
		||||
  assert(p)
 | 
			
		||||
  assert(options)
 | 
			
		||||
  assert(typeof cb === 'function')
 | 
			
		||||
 | 
			
		||||
  options.chmod(p, 0o666, er2 => {
 | 
			
		||||
    if (er2)
 | 
			
		||||
      cb(er2.code === "ENOENT" ? null : er)
 | 
			
		||||
    else
 | 
			
		||||
      options.stat(p, (er3, stats) => {
 | 
			
		||||
        if (er3)
 | 
			
		||||
          cb(er3.code === "ENOENT" ? null : er)
 | 
			
		||||
        else if (stats.isDirectory())
 | 
			
		||||
          rmdir(p, options, er, cb)
 | 
			
		||||
        else
 | 
			
		||||
          options.unlink(p, cb)
 | 
			
		||||
      })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const fixWinEPERMSync = (p, options, er) => {
 | 
			
		||||
  assert(p)
 | 
			
		||||
  assert(options)
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    options.chmodSync(p, 0o666)
 | 
			
		||||
  } catch (er2) {
 | 
			
		||||
    if (er2.code === "ENOENT")
 | 
			
		||||
      return
 | 
			
		||||
    else
 | 
			
		||||
      throw er
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let stats
 | 
			
		||||
  try {
 | 
			
		||||
    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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rmdir = (p, options, originalEr, cb) => {
 | 
			
		||||
  assert(p)
 | 
			
		||||
  assert(options)
 | 
			
		||||
  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, 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)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rmkids = (p, options, cb) => {
 | 
			
		||||
  assert(p)
 | 
			
		||||
  assert(options)
 | 
			
		||||
  assert(typeof cb === 'function')
 | 
			
		||||
 | 
			
		||||
  options.readdir(p, (er, files) => {
 | 
			
		||||
    if (er)
 | 
			
		||||
      return cb(er)
 | 
			
		||||
    let n = files.length
 | 
			
		||||
    if (n === 0)
 | 
			
		||||
      return options.rmdir(p, cb)
 | 
			
		||||
    let errState
 | 
			
		||||
    files.forEach(f => {
 | 
			
		||||
      rimraf(path.join(p, f), options, 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.
 | 
			
		||||
const 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')
 | 
			
		||||
 | 
			
		||||
  let 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 (let i = 0; i < results.length; i++) {
 | 
			
		||||
    const p = results[i]
 | 
			
		||||
 | 
			
		||||
    let st
 | 
			
		||||
    try {
 | 
			
		||||
      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)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rmdirSync = (p, options, originalEr) => {
 | 
			
		||||
  assert(p)
 | 
			
		||||
  assert(options)
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rmkidsSync = (p, options) => {
 | 
			
		||||
  assert(p)
 | 
			
		||||
  assert(options)
 | 
			
		||||
  options.readdirSync(p).forEach(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.
 | 
			
		||||
  const retries = isWindows ? 100 : 1
 | 
			
		||||
  let i = 0
 | 
			
		||||
  do {
 | 
			
		||||
    let threw = true
 | 
			
		||||
    try {
 | 
			
		||||
      const ret = options.rmdirSync(p, options)
 | 
			
		||||
      threw = false
 | 
			
		||||
      return ret
 | 
			
		||||
    } finally {
 | 
			
		||||
      if (++i < retries && threw)
 | 
			
		||||
        continue
 | 
			
		||||
    }
 | 
			
		||||
  } while (true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = rimraf
 | 
			
		||||
rimraf.sync = rimrafSync
 | 
			
		||||
		Reference in New Issue
	
	Block a user