1 module.exports = rimraf
2 rimraf.sync = rimrafSync
4 var path = require("path")
9 exports.EMFILE_MAX = 1000
10 exports.BUSYTRIES_MAX = 3
12 var isWindows = (process.platform === "win32")
14 function rimraf (p, cb) {
15 if (!cb) throw new Error("No callback passed to rimraf()")
18 rimraf_(p, function CB (er) {
20 if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY") &&
21 busyTries < exports.BUSYTRIES_MAX) {
23 var time = busyTries * 100
24 // try again, with the same exact callback as this one.
25 return setTimeout(function () {
30 // this one won't happen if graceful-fs is used.
31 if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) {
32 return setTimeout(function () {
38 if (er.code === "ENOENT") er = null
46 // Two possible strategies.
47 // 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR
48 // 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR
50 // Both result in an extra syscall when you guess wrong. However, there
51 // are likely far more normal files in the world than directories. This
52 // is based on the assumption that a the average number of files per
55 // If anyone ever complains about this, then I guess the strategy could
56 // be made configurable somehow. But until then, YAGNI.
57 function rimraf_ (p, cb) {
58 fs.unlink(p, function (er) {
60 if (er.code === "ENOENT")
62 if (er.code === "EPERM")
63 return (isWindows) ? fixWinEPERM(p, er, cb) : rmdir(p, er, cb)
64 if (er.code === "EISDIR")
65 return rmdir(p, er, cb)
71 function fixWinEPERM (p, er, cb) {
72 fs.chmod(p, 666, function (er2) {
74 cb(er2.code === "ENOENT" ? null : er)
76 fs.stat(p, function(er3, stats) {
78 cb(er3.code === "ENOENT" ? null : er)
79 else if (stats.isDirectory())
87 function fixWinEPERMSync (p, er, cb) {
91 if (er2.code !== "ENOENT")
96 var stats = fs.statSync(p)
102 if (stats.isDirectory())
108 function rmdir (p, originalEr, cb) {
109 // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
110 // if we guessed wrong, and it's not a directory, then
111 // raise the original error.
112 fs.rmdir(p, function (er) {
113 if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST"))
115 else if (er && er.code === "ENOTDIR")
122 function rmkids(p, cb) {
123 fs.readdir(p, function (er, files) {
128 return fs.rmdir(p, cb)
130 files.forEach(function (f) {
131 rimraf(path.join(p, f), function (er) {
135 return cb(errState = er)
143 // this looks simpler, and is strictly *faster*, but will
144 // tie up the JavaScript thread and fail on excessively
145 // deep directory trees.
146 function rimrafSync (p) {
150 if (er.code === "ENOENT")
152 if (er.code === "EPERM")
153 return isWindows ? fixWinEPERMSync(p, er) : rmdirSync(p, er)
154 if (er.code !== "EISDIR")
160 function rmdirSync (p, originalEr) {
164 if (er.code === "ENOENT")
166 if (er.code === "ENOTDIR")
168 if (er.code === "ENOTEMPTY" || er.code === "EEXIST")
173 function rmkidsSync (p) {
174 fs.readdirSync(p).forEach(function (f) {
175 rimrafSync(path.join(p, f))