1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
module.exports = rimraf
rimraf.sync = rimrafSync
var path = require("path")
, fs
try {
// optional dependency
fs = require("graceful-fs")
} catch (er) {
fs = require("fs")
}
var lstat = process.platform === "win32" ? "stat" : "lstat"
, lstatSync = lstat + "Sync"
// for EMFILE handling
var timeout = 0
exports.EMFILE_MAX = 1000
exports.BUSYTRIES_MAX = 3
function rimraf (p, cb) {
if (!cb) throw new Error("No callback passed to rimraf()")
var busyTries = 0
rimraf_(p, function CB (er) {
if (er) {
if (er.code === "EBUSY" && busyTries < exports.BUSYTRIES_MAX) {
var time = (exports.BUSYTRIES_MAX - busyTries) * 100
busyTries ++
// try again, with the same exact callback as this one.
return setTimeout(function () {
rimraf_(p, CB)
})
}
// this one won't happen if graceful-fs is used.
if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) {
return setTimeout(function () {
rimraf_(p, CB)
}, timeout ++)
}
// already gone
if (er.code === "ENOENT") er = null
}
timeout = 0
cb(er)
})
}
function rimraf_ (p, cb) {
fs[lstat](p, function (er, s) {
if (er) {
// already gone
if (er.code === "ENOENT") return cb()
// some other kind of error, permissions, etc.
return cb(er)
}
return rm_(p, s, false, cb)
})
}
var myGid = function myGid () {
var g = process.getuid && process.getgid()
myGid = function myGid () { return g }
return g
}
var myUid = function myUid () {
var u = process.getuid && process.getuid()
myUid = function myUid () { return u }
return u
}
function writable (s) {
var mode = s.mode || 0777
, uid = myUid()
, gid = myGid()
return (mode & 0002)
|| (gid === s.gid && (mode & 0020))
|| (uid === s.uid && (mode & 0200))
}
function rm_ (p, s, didWritableCheck, cb) {
if (!didWritableCheck && !writable(s)) {
// make file writable
// user/group/world, doesn't matter at this point
// since it's about to get nuked.
return fs.chmod(p, s.mode | 0222, function (er) {
if (er) return cb(er)
rm_(p, s, true, cb)
})
}
if (!s.isDirectory()) {
return fs.unlink(p, cb)
}
// directory
fs.readdir(p, function (er, files) {
if (er) return cb(er)
asyncForEach(files.map(function (f) {
return path.join(p, f)
}), function (file, cb) {
rimraf(file, cb)
}, function (er) {
if (er) return cb(er)
fs.rmdir(p, cb)
})
})
}
function asyncForEach (list, fn, cb) {
if (!list.length) cb()
var c = list.length
, errState = null
list.forEach(function (item, i, list) {
fn(item, function (er) {
if (errState) return
if (er) return cb(errState = er)
if (-- c === 0) return cb()
})
})
}
// this looks simpler, but it will fail with big directory trees,
// or on slow stupid awful cygwin filesystems
function rimrafSync (p) {
try {
var s = fs[lstatSync](p)
} catch (er) {
if (er.code === "ENOENT") return
throw er
}
if (!writable(s)) {
fs.chmodSync(p, s.mode | 0222)
}
if (!s.isDirectory()) return fs.unlinkSync(p)
fs.readdirSync(p).forEach(function (f) {
rimrafSync(path.join(p, f))
})
fs.rmdirSync(p)
}
|