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
							 |