rimraf 2.7.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +41 -23
- package/package.json +2 -2
- package/rimraf.js +67 -71
package/bin.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const rimraf = require('./')
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const path = require('path')
|
|
6
|
+
|
|
7
|
+
const isRoot = arg => /^(\/|[a-zA-Z]:\\)$/.test(path.resolve(arg))
|
|
8
|
+
const filterOutRoot = arg => {
|
|
9
|
+
const ok = preserveRoot === false || !isRoot(arg)
|
|
10
|
+
if (!ok) {
|
|
11
|
+
console.error(`refusing to remove ${arg}`)
|
|
12
|
+
console.error('Set --no-preserve-root to allow this')
|
|
13
|
+
}
|
|
14
|
+
return ok
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let help = false
|
|
18
|
+
let dashdash = false
|
|
19
|
+
let noglob = false
|
|
20
|
+
let preserveRoot = true
|
|
21
|
+
const args = process.argv.slice(2).filter(arg => {
|
|
9
22
|
if (dashdash)
|
|
10
23
|
return !!arg
|
|
11
24
|
else if (arg === '--')
|
|
@@ -16,35 +29,40 @@ var args = process.argv.slice(2).filter(function(arg) {
|
|
|
16
29
|
noglob = false
|
|
17
30
|
else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/))
|
|
18
31
|
help = true
|
|
32
|
+
else if (arg === '--preserve-root')
|
|
33
|
+
preserveRoot = true
|
|
34
|
+
else if (arg === '--no-preserve-root')
|
|
35
|
+
preserveRoot = false
|
|
19
36
|
else
|
|
20
37
|
return !!arg
|
|
21
|
-
})
|
|
38
|
+
}).filter(arg => !preserveRoot || filterOutRoot(arg))
|
|
39
|
+
|
|
40
|
+
const go = n => {
|
|
41
|
+
if (n >= args.length)
|
|
42
|
+
return
|
|
43
|
+
const options = noglob ? { glob: false } : {}
|
|
44
|
+
rimraf(args[n], options, er => {
|
|
45
|
+
if (er)
|
|
46
|
+
throw er
|
|
47
|
+
go(n+1)
|
|
48
|
+
})
|
|
49
|
+
}
|
|
22
50
|
|
|
23
51
|
if (help || args.length === 0) {
|
|
24
52
|
// If they didn't ask for help, then this is not a "success"
|
|
25
|
-
|
|
53
|
+
const log = help ? console.log : console.error
|
|
26
54
|
log('Usage: rimraf <path> [<path> ...]')
|
|
27
55
|
log('')
|
|
28
56
|
log(' Deletes all files and folders at "path" recursively.')
|
|
29
57
|
log('')
|
|
30
58
|
log('Options:')
|
|
31
59
|
log('')
|
|
32
|
-
log(' -h, --help
|
|
33
|
-
log(' -G, --no-glob
|
|
34
|
-
log(' -g, --glob
|
|
60
|
+
log(' -h, --help Display this usage info')
|
|
61
|
+
log(' -G, --no-glob Do not expand glob patterns in arguments')
|
|
62
|
+
log(' -g, --glob Expand glob patterns in arguments (default)')
|
|
63
|
+
log(' --preserve-root Do not remove \'/\' (default)')
|
|
64
|
+
log(' --no-preserve-root Do not treat \'/\' specially')
|
|
65
|
+
log(' -- Stop parsing flags')
|
|
35
66
|
process.exit(help ? 0 : 1)
|
|
36
67
|
} else
|
|
37
68
|
go(0)
|
|
38
|
-
|
|
39
|
-
function go (n) {
|
|
40
|
-
if (n >= args.length)
|
|
41
|
-
return
|
|
42
|
-
var options = {}
|
|
43
|
-
if (noglob)
|
|
44
|
-
options = { glob: false }
|
|
45
|
-
rimraf(args[n], options, function (er) {
|
|
46
|
-
if (er)
|
|
47
|
-
throw er
|
|
48
|
-
go(n+1)
|
|
49
|
-
})
|
|
50
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rimraf",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"main": "rimraf.js",
|
|
5
5
|
"description": "A deep deletion module for node (like `rm -rf`)",
|
|
6
6
|
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"preversion": "npm test",
|
|
11
11
|
"postversion": "npm publish",
|
|
12
|
-
"postpublish": "git push origin --
|
|
12
|
+
"postpublish": "git push origin --follow-tags",
|
|
13
13
|
"test": "tap test/*.js"
|
|
14
14
|
},
|
|
15
15
|
"bin": "./bin.js",
|
package/rimraf.js
CHANGED
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var path = require("path")
|
|
6
|
-
var fs = require("fs")
|
|
7
|
-
var glob = undefined
|
|
1
|
+
const assert = require("assert")
|
|
2
|
+
const path = require("path")
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
let glob = undefined
|
|
8
5
|
try {
|
|
9
6
|
glob = require("glob")
|
|
10
7
|
} catch (_err) {
|
|
11
8
|
// treat glob as optional.
|
|
12
9
|
}
|
|
13
|
-
var _0666 = parseInt('666', 8)
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
const defaultGlobOpts = {
|
|
16
12
|
nosort: true,
|
|
17
13
|
silent: true
|
|
18
14
|
}
|
|
19
15
|
|
|
20
16
|
// for EMFILE handling
|
|
21
|
-
|
|
17
|
+
let timeout = 0
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
const isWindows = (process.platform === "win32")
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
const defaults = options => {
|
|
22
|
+
const methods = [
|
|
27
23
|
'unlink',
|
|
28
24
|
'chmod',
|
|
29
25
|
'stat',
|
|
@@ -31,7 +27,7 @@ function defaults (options) {
|
|
|
31
27
|
'rmdir',
|
|
32
28
|
'readdir'
|
|
33
29
|
]
|
|
34
|
-
methods.forEach(
|
|
30
|
+
methods.forEach(m => {
|
|
35
31
|
options[m] = options[m] || fs[m]
|
|
36
32
|
m = m + 'Sync'
|
|
37
33
|
options[m] = options[m] || fs[m]
|
|
@@ -49,7 +45,7 @@ function defaults (options) {
|
|
|
49
45
|
options.glob = options.glob || defaultGlobOpts
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
const rimraf = (p, options, cb) => {
|
|
53
49
|
if (typeof options === 'function') {
|
|
54
50
|
cb = options
|
|
55
51
|
options = {}
|
|
@@ -63,27 +59,17 @@ function rimraf (p, options, cb) {
|
|
|
63
59
|
|
|
64
60
|
defaults(options)
|
|
65
61
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (options.disableGlob || !glob.hasMagic(p))
|
|
71
|
-
return afterGlob(null, [p])
|
|
72
|
-
|
|
73
|
-
options.lstat(p, function (er, stat) {
|
|
74
|
-
if (!er)
|
|
75
|
-
return afterGlob(null, [p])
|
|
62
|
+
let busyTries = 0
|
|
63
|
+
let errState = null
|
|
64
|
+
let n = 0
|
|
76
65
|
|
|
77
|
-
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
function next (er) {
|
|
66
|
+
const next = (er) => {
|
|
81
67
|
errState = errState || er
|
|
82
68
|
if (--n === 0)
|
|
83
69
|
cb(errState)
|
|
84
70
|
}
|
|
85
71
|
|
|
86
|
-
|
|
72
|
+
const afterGlob = (er, results) => {
|
|
87
73
|
if (er)
|
|
88
74
|
return cb(er)
|
|
89
75
|
|
|
@@ -91,24 +77,19 @@ function rimraf (p, options, cb) {
|
|
|
91
77
|
if (n === 0)
|
|
92
78
|
return cb()
|
|
93
79
|
|
|
94
|
-
results.forEach(
|
|
95
|
-
|
|
80
|
+
results.forEach(p => {
|
|
81
|
+
const CB = (er) => {
|
|
96
82
|
if (er) {
|
|
97
83
|
if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
|
|
98
84
|
busyTries < options.maxBusyTries) {
|
|
99
85
|
busyTries ++
|
|
100
|
-
var time = busyTries * 100
|
|
101
86
|
// try again, with the same exact callback as this one.
|
|
102
|
-
return setTimeout(
|
|
103
|
-
rimraf_(p, options, CB)
|
|
104
|
-
}, time)
|
|
87
|
+
return setTimeout(() => rimraf_(p, options, CB), busyTries * 100)
|
|
105
88
|
}
|
|
106
89
|
|
|
107
90
|
// this one won't happen if graceful-fs is used.
|
|
108
91
|
if (er.code === "EMFILE" && timeout < options.emfileWait) {
|
|
109
|
-
return setTimeout(
|
|
110
|
-
rimraf_(p, options, CB)
|
|
111
|
-
}, timeout ++)
|
|
92
|
+
return setTimeout(() => rimraf_(p, options, CB), timeout ++)
|
|
112
93
|
}
|
|
113
94
|
|
|
114
95
|
// already gone
|
|
@@ -117,9 +98,21 @@ function rimraf (p, options, cb) {
|
|
|
117
98
|
|
|
118
99
|
timeout = 0
|
|
119
100
|
next(er)
|
|
120
|
-
}
|
|
101
|
+
}
|
|
102
|
+
rimraf_(p, options, CB)
|
|
121
103
|
})
|
|
122
104
|
}
|
|
105
|
+
|
|
106
|
+
if (options.disableGlob || !glob.hasMagic(p))
|
|
107
|
+
return afterGlob(null, [p])
|
|
108
|
+
|
|
109
|
+
options.lstat(p, (er, stat) => {
|
|
110
|
+
if (!er)
|
|
111
|
+
return afterGlob(null, [p])
|
|
112
|
+
|
|
113
|
+
glob(p, options.glob, afterGlob)
|
|
114
|
+
})
|
|
115
|
+
|
|
123
116
|
}
|
|
124
117
|
|
|
125
118
|
// Two possible strategies.
|
|
@@ -133,14 +126,14 @@ function rimraf (p, options, cb) {
|
|
|
133
126
|
//
|
|
134
127
|
// If anyone ever complains about this, then I guess the strategy could
|
|
135
128
|
// be made configurable somehow. But until then, YAGNI.
|
|
136
|
-
|
|
129
|
+
const rimraf_ = (p, options, cb) => {
|
|
137
130
|
assert(p)
|
|
138
131
|
assert(options)
|
|
139
132
|
assert(typeof cb === 'function')
|
|
140
133
|
|
|
141
134
|
// sunos lets the root user unlink directories, which is... weird.
|
|
142
135
|
// so we have to lstat here and make sure it's not a dir.
|
|
143
|
-
options.lstat(p,
|
|
136
|
+
options.lstat(p, (er, st) => {
|
|
144
137
|
if (er && er.code === "ENOENT")
|
|
145
138
|
return cb(null)
|
|
146
139
|
|
|
@@ -151,7 +144,7 @@ function rimraf_ (p, options, cb) {
|
|
|
151
144
|
if (st && st.isDirectory())
|
|
152
145
|
return rmdir(p, options, er, cb)
|
|
153
146
|
|
|
154
|
-
options.unlink(p,
|
|
147
|
+
options.unlink(p, er => {
|
|
155
148
|
if (er) {
|
|
156
149
|
if (er.code === "ENOENT")
|
|
157
150
|
return cb(null)
|
|
@@ -167,18 +160,18 @@ function rimraf_ (p, options, cb) {
|
|
|
167
160
|
})
|
|
168
161
|
}
|
|
169
162
|
|
|
170
|
-
|
|
163
|
+
const fixWinEPERM = (p, options, er, cb) => {
|
|
171
164
|
assert(p)
|
|
172
165
|
assert(options)
|
|
173
166
|
assert(typeof cb === 'function')
|
|
174
167
|
if (er)
|
|
175
168
|
assert(er instanceof Error)
|
|
176
169
|
|
|
177
|
-
options.chmod(p,
|
|
170
|
+
options.chmod(p, 0o666, er2 => {
|
|
178
171
|
if (er2)
|
|
179
172
|
cb(er2.code === "ENOENT" ? null : er)
|
|
180
173
|
else
|
|
181
|
-
options.stat(p,
|
|
174
|
+
options.stat(p, (er3, stats) => {
|
|
182
175
|
if (er3)
|
|
183
176
|
cb(er3.code === "ENOENT" ? null : er)
|
|
184
177
|
else if (stats.isDirectory())
|
|
@@ -189,14 +182,14 @@ function fixWinEPERM (p, options, er, cb) {
|
|
|
189
182
|
})
|
|
190
183
|
}
|
|
191
184
|
|
|
192
|
-
|
|
185
|
+
const fixWinEPERMSync = (p, options, er) => {
|
|
193
186
|
assert(p)
|
|
194
187
|
assert(options)
|
|
195
188
|
if (er)
|
|
196
189
|
assert(er instanceof Error)
|
|
197
190
|
|
|
198
191
|
try {
|
|
199
|
-
options.chmodSync(p,
|
|
192
|
+
options.chmodSync(p, 0o666)
|
|
200
193
|
} catch (er2) {
|
|
201
194
|
if (er2.code === "ENOENT")
|
|
202
195
|
return
|
|
@@ -204,8 +197,9 @@ function fixWinEPERMSync (p, options, er) {
|
|
|
204
197
|
throw er
|
|
205
198
|
}
|
|
206
199
|
|
|
200
|
+
let stats
|
|
207
201
|
try {
|
|
208
|
-
|
|
202
|
+
stats = options.statSync(p)
|
|
209
203
|
} catch (er3) {
|
|
210
204
|
if (er3.code === "ENOENT")
|
|
211
205
|
return
|
|
@@ -219,7 +213,7 @@ function fixWinEPERMSync (p, options, er) {
|
|
|
219
213
|
options.unlinkSync(p)
|
|
220
214
|
}
|
|
221
215
|
|
|
222
|
-
|
|
216
|
+
const rmdir = (p, options, originalEr, cb) => {
|
|
223
217
|
assert(p)
|
|
224
218
|
assert(options)
|
|
225
219
|
if (originalEr)
|
|
@@ -229,7 +223,7 @@ function rmdir (p, options, originalEr, cb) {
|
|
|
229
223
|
// try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
|
|
230
224
|
// if we guessed wrong, and it's not a directory, then
|
|
231
225
|
// raise the original error.
|
|
232
|
-
options.rmdir(p,
|
|
226
|
+
options.rmdir(p, er => {
|
|
233
227
|
if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))
|
|
234
228
|
rmkids(p, options, cb)
|
|
235
229
|
else if (er && er.code === "ENOTDIR")
|
|
@@ -239,20 +233,20 @@ function rmdir (p, options, originalEr, cb) {
|
|
|
239
233
|
})
|
|
240
234
|
}
|
|
241
235
|
|
|
242
|
-
|
|
236
|
+
const rmkids = (p, options, cb) => {
|
|
243
237
|
assert(p)
|
|
244
238
|
assert(options)
|
|
245
239
|
assert(typeof cb === 'function')
|
|
246
240
|
|
|
247
|
-
options.readdir(p,
|
|
241
|
+
options.readdir(p, (er, files) => {
|
|
248
242
|
if (er)
|
|
249
243
|
return cb(er)
|
|
250
|
-
|
|
244
|
+
let n = files.length
|
|
251
245
|
if (n === 0)
|
|
252
246
|
return options.rmdir(p, cb)
|
|
253
|
-
|
|
254
|
-
files.forEach(
|
|
255
|
-
rimraf(path.join(p, f), options,
|
|
247
|
+
let errState
|
|
248
|
+
files.forEach(f => {
|
|
249
|
+
rimraf(path.join(p, f), options, er => {
|
|
256
250
|
if (errState)
|
|
257
251
|
return
|
|
258
252
|
if (er)
|
|
@@ -267,7 +261,7 @@ function rmkids(p, options, cb) {
|
|
|
267
261
|
// this looks simpler, and is strictly *faster*, but will
|
|
268
262
|
// tie up the JavaScript thread and fail on excessively
|
|
269
263
|
// deep directory trees.
|
|
270
|
-
|
|
264
|
+
const rimrafSync = (p, options) => {
|
|
271
265
|
options = options || {}
|
|
272
266
|
defaults(options)
|
|
273
267
|
|
|
@@ -276,7 +270,7 @@ function rimrafSync (p, options) {
|
|
|
276
270
|
assert(options, 'rimraf: missing options')
|
|
277
271
|
assert.equal(typeof options, 'object', 'rimraf: options should be object')
|
|
278
272
|
|
|
279
|
-
|
|
273
|
+
let results
|
|
280
274
|
|
|
281
275
|
if (options.disableGlob || !glob.hasMagic(p)) {
|
|
282
276
|
results = [p]
|
|
@@ -292,11 +286,12 @@ function rimrafSync (p, options) {
|
|
|
292
286
|
if (!results.length)
|
|
293
287
|
return
|
|
294
288
|
|
|
295
|
-
for (
|
|
296
|
-
|
|
289
|
+
for (let i = 0; i < results.length; i++) {
|
|
290
|
+
const p = results[i]
|
|
297
291
|
|
|
292
|
+
let st
|
|
298
293
|
try {
|
|
299
|
-
|
|
294
|
+
st = options.lstatSync(p)
|
|
300
295
|
} catch (er) {
|
|
301
296
|
if (er.code === "ENOENT")
|
|
302
297
|
return
|
|
@@ -325,7 +320,7 @@ function rimrafSync (p, options) {
|
|
|
325
320
|
}
|
|
326
321
|
}
|
|
327
322
|
|
|
328
|
-
|
|
323
|
+
const rmdirSync = (p, options, originalEr) => {
|
|
329
324
|
assert(p)
|
|
330
325
|
assert(options)
|
|
331
326
|
if (originalEr)
|
|
@@ -343,12 +338,10 @@ function rmdirSync (p, options, originalEr) {
|
|
|
343
338
|
}
|
|
344
339
|
}
|
|
345
340
|
|
|
346
|
-
|
|
341
|
+
const rmkidsSync = (p, options) => {
|
|
347
342
|
assert(p)
|
|
348
343
|
assert(options)
|
|
349
|
-
options.readdirSync(p).forEach(
|
|
350
|
-
rimrafSync(path.join(p, f), options)
|
|
351
|
-
})
|
|
344
|
+
options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))
|
|
352
345
|
|
|
353
346
|
// We only end up here once we got ENOTEMPTY at least once, and
|
|
354
347
|
// at this point, we are guaranteed to have removed all the kids.
|
|
@@ -356,12 +349,12 @@ function rmkidsSync (p, options) {
|
|
|
356
349
|
// try really hard to delete stuff on windows, because it has a
|
|
357
350
|
// PROFOUNDLY annoying habit of not closing handles promptly when
|
|
358
351
|
// files are deleted, resulting in spurious ENOTEMPTY errors.
|
|
359
|
-
|
|
360
|
-
|
|
352
|
+
const retries = isWindows ? 100 : 1
|
|
353
|
+
let i = 0
|
|
361
354
|
do {
|
|
362
|
-
|
|
355
|
+
let threw = true
|
|
363
356
|
try {
|
|
364
|
-
|
|
357
|
+
const ret = options.rmdirSync(p, options)
|
|
365
358
|
threw = false
|
|
366
359
|
return ret
|
|
367
360
|
} finally {
|
|
@@ -370,3 +363,6 @@ function rmkidsSync (p, options) {
|
|
|
370
363
|
}
|
|
371
364
|
} while (true)
|
|
372
365
|
}
|
|
366
|
+
|
|
367
|
+
module.exports = rimraf
|
|
368
|
+
rimraf.sync = rimrafSync
|