rimraf 2.7.0 → 3.0.2

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.
Files changed (4) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/bin.js +41 -23
  3. package/package.json +5 -2
  4. package/rimraf.js +66 -78
package/CHANGELOG.md ADDED
@@ -0,0 +1,65 @@
1
+ # v3.0
2
+
3
+ - Add `--preserve-root` option to executable (default true)
4
+ - Drop support for Node.js below version 6
5
+
6
+ # v2.7
7
+
8
+ - Make `glob` an optional dependency
9
+
10
+ # 2.6
11
+
12
+ - Retry on EBUSY on non-windows platforms as well
13
+ - Make `rimraf.sync` 10000% more reliable on Windows
14
+
15
+ # 2.5
16
+
17
+ - Handle Windows EPERM when lstat-ing read-only dirs
18
+ - Add glob option to pass options to glob
19
+
20
+ # 2.4
21
+
22
+ - Add EPERM to delay/retry loop
23
+ - Add `disableGlob` option
24
+
25
+ # 2.3
26
+
27
+ - Make maxBusyTries and emfileWait configurable
28
+ - Handle weird SunOS unlink-dir issue
29
+ - Glob the CLI arg for better Windows support
30
+
31
+ # 2.2
32
+
33
+ - Handle ENOENT properly on Windows
34
+ - Allow overriding fs methods
35
+ - Treat EPERM as indicative of non-empty dir
36
+ - Remove optional graceful-fs dep
37
+ - Consistently return null error instead of undefined on success
38
+ - win32: Treat ENOTEMPTY the same as EBUSY
39
+ - Add `rimraf` binary
40
+
41
+ # 2.1
42
+
43
+ - Fix SunOS error code for a non-empty directory
44
+ - Try rmdir before readdir
45
+ - Treat EISDIR like EPERM
46
+ - Remove chmod
47
+ - Remove lstat polyfill, node 0.7 is not supported
48
+
49
+ # 2.0
50
+
51
+ - Fix myGid call to check process.getgid
52
+ - Simplify the EBUSY backoff logic.
53
+ - Use fs.lstat in node >= 0.7.9
54
+ - Remove gently option
55
+ - remove fiber implementation
56
+ - Delete files that are marked read-only
57
+
58
+ # 1.0
59
+
60
+ - Allow ENOENT in sync method
61
+ - Throw when no callback is provided
62
+ - Make opts.gently an absolute path
63
+ - use 'stat' if 'lstat' is not available
64
+ - Consistent error naming, and rethrow non-ENOENT stat errors
65
+ - add fiber implementation
package/bin.js CHANGED
@@ -1,11 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- var rimraf = require('./')
3
+ const rimraf = require('./')
4
4
 
5
- var help = false
6
- var dashdash = false
7
- var noglob = false
8
- var args = process.argv.slice(2).filter(function(arg) {
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
- var log = help ? console.log : console.error
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 Display this usage info')
33
- log(' -G, --no-glob Do not expand glob patterns in arguments')
34
- log(' -g, --glob Expand glob patterns in arguments (default)')
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": "2.7.0",
3
+ "version": "3.0.2",
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 --all; git push origin --tags",
12
+ "postpublish": "git push origin --follow-tags",
13
13
  "test": "tap test/*.js"
14
14
  },
15
15
  "bin": "./bin.js",
@@ -25,5 +25,8 @@
25
25
  "devDependencies": {
26
26
  "mkdirp": "^0.5.1",
27
27
  "tap": "^12.1.1"
28
+ },
29
+ "funding": {
30
+ "url": "https://github.com/sponsors/isaacs"
28
31
  }
29
32
  }
package/rimraf.js CHANGED
@@ -1,29 +1,25 @@
1
- module.exports = rimraf
2
- rimraf.sync = rimrafSync
3
-
4
- var assert = require("assert")
5
- var path = require("path")
6
- var fs = require("fs")
1
+ const assert = require("assert")
2
+ const path = require("path")
3
+ const fs = require("fs")
7
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
- var defaultGlobOpts = {
11
+ const defaultGlobOpts = {
16
12
  nosort: true,
17
13
  silent: true
18
14
  }
19
15
 
20
16
  // for EMFILE handling
21
- var timeout = 0
17
+ let timeout = 0
22
18
 
23
- var isWindows = (process.platform === "win32")
19
+ const isWindows = (process.platform === "win32")
24
20
 
25
- function defaults (options) {
26
- var methods = [
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(function(m) {
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
- function rimraf (p, options, cb) {
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
- var busyTries = 0
67
- var errState = null
68
- var n = 0
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
- glob(p, options.glob, afterGlob)
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
- function afterGlob (er, results) {
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(function (p) {
95
- rimraf_(p, options, function CB (er) {
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(function () {
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(function () {
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
- function rimraf_ (p, options, cb) {
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, function (er, st) {
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, function (er) {
147
+ options.unlink(p, er => {
155
148
  if (er) {
156
149
  if (er.code === "ENOENT")
157
150
  return cb(null)
@@ -167,18 +160,16 @@ function rimraf_ (p, options, cb) {
167
160
  })
168
161
  }
169
162
 
170
- function fixWinEPERM (p, options, er, cb) {
163
+ const fixWinEPERM = (p, options, er, cb) => {
171
164
  assert(p)
172
165
  assert(options)
173
166
  assert(typeof cb === 'function')
174
- if (er)
175
- assert(er instanceof Error)
176
167
 
177
- options.chmod(p, _0666, function (er2) {
168
+ options.chmod(p, 0o666, er2 => {
178
169
  if (er2)
179
170
  cb(er2.code === "ENOENT" ? null : er)
180
171
  else
181
- options.stat(p, function(er3, stats) {
172
+ options.stat(p, (er3, stats) => {
182
173
  if (er3)
183
174
  cb(er3.code === "ENOENT" ? null : er)
184
175
  else if (stats.isDirectory())
@@ -189,14 +180,12 @@ function fixWinEPERM (p, options, er, cb) {
189
180
  })
190
181
  }
191
182
 
192
- function fixWinEPERMSync (p, options, er) {
183
+ const fixWinEPERMSync = (p, options, er) => {
193
184
  assert(p)
194
185
  assert(options)
195
- if (er)
196
- assert(er instanceof Error)
197
186
 
198
187
  try {
199
- options.chmodSync(p, _0666)
188
+ options.chmodSync(p, 0o666)
200
189
  } catch (er2) {
201
190
  if (er2.code === "ENOENT")
202
191
  return
@@ -204,8 +193,9 @@ function fixWinEPERMSync (p, options, er) {
204
193
  throw er
205
194
  }
206
195
 
196
+ let stats
207
197
  try {
208
- var stats = options.statSync(p)
198
+ stats = options.statSync(p)
209
199
  } catch (er3) {
210
200
  if (er3.code === "ENOENT")
211
201
  return
@@ -219,17 +209,15 @@ function fixWinEPERMSync (p, options, er) {
219
209
  options.unlinkSync(p)
220
210
  }
221
211
 
222
- function rmdir (p, options, originalEr, cb) {
212
+ const rmdir = (p, options, originalEr, cb) => {
223
213
  assert(p)
224
214
  assert(options)
225
- if (originalEr)
226
- assert(originalEr instanceof Error)
227
215
  assert(typeof cb === 'function')
228
216
 
229
217
  // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
230
218
  // if we guessed wrong, and it's not a directory, then
231
219
  // raise the original error.
232
- options.rmdir(p, function (er) {
220
+ options.rmdir(p, er => {
233
221
  if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))
234
222
  rmkids(p, options, cb)
235
223
  else if (er && er.code === "ENOTDIR")
@@ -239,20 +227,20 @@ function rmdir (p, options, originalEr, cb) {
239
227
  })
240
228
  }
241
229
 
242
- function rmkids(p, options, cb) {
230
+ const rmkids = (p, options, cb) => {
243
231
  assert(p)
244
232
  assert(options)
245
233
  assert(typeof cb === 'function')
246
234
 
247
- options.readdir(p, function (er, files) {
235
+ options.readdir(p, (er, files) => {
248
236
  if (er)
249
237
  return cb(er)
250
- var n = files.length
238
+ let n = files.length
251
239
  if (n === 0)
252
240
  return options.rmdir(p, cb)
253
- var errState
254
- files.forEach(function (f) {
255
- rimraf(path.join(p, f), options, function (er) {
241
+ let errState
242
+ files.forEach(f => {
243
+ rimraf(path.join(p, f), options, er => {
256
244
  if (errState)
257
245
  return
258
246
  if (er)
@@ -267,7 +255,7 @@ function rmkids(p, options, cb) {
267
255
  // this looks simpler, and is strictly *faster*, but will
268
256
  // tie up the JavaScript thread and fail on excessively
269
257
  // deep directory trees.
270
- function rimrafSync (p, options) {
258
+ const rimrafSync = (p, options) => {
271
259
  options = options || {}
272
260
  defaults(options)
273
261
 
@@ -276,7 +264,7 @@ function rimrafSync (p, options) {
276
264
  assert(options, 'rimraf: missing options')
277
265
  assert.equal(typeof options, 'object', 'rimraf: options should be object')
278
266
 
279
- var results
267
+ let results
280
268
 
281
269
  if (options.disableGlob || !glob.hasMagic(p)) {
282
270
  results = [p]
@@ -292,11 +280,12 @@ function rimrafSync (p, options) {
292
280
  if (!results.length)
293
281
  return
294
282
 
295
- for (var i = 0; i < results.length; i++) {
296
- var p = results[i]
283
+ for (let i = 0; i < results.length; i++) {
284
+ const p = results[i]
297
285
 
286
+ let st
298
287
  try {
299
- var st = options.lstatSync(p)
288
+ st = options.lstatSync(p)
300
289
  } catch (er) {
301
290
  if (er.code === "ENOENT")
302
291
  return
@@ -325,11 +314,9 @@ function rimrafSync (p, options) {
325
314
  }
326
315
  }
327
316
 
328
- function rmdirSync (p, options, originalEr) {
317
+ const rmdirSync = (p, options, originalEr) => {
329
318
  assert(p)
330
319
  assert(options)
331
- if (originalEr)
332
- assert(originalEr instanceof Error)
333
320
 
334
321
  try {
335
322
  options.rmdirSync(p)
@@ -343,12 +330,10 @@ function rmdirSync (p, options, originalEr) {
343
330
  }
344
331
  }
345
332
 
346
- function rmkidsSync (p, options) {
333
+ const rmkidsSync = (p, options) => {
347
334
  assert(p)
348
335
  assert(options)
349
- options.readdirSync(p).forEach(function (f) {
350
- rimrafSync(path.join(p, f), options)
351
- })
336
+ options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))
352
337
 
353
338
  // We only end up here once we got ENOTEMPTY at least once, and
354
339
  // at this point, we are guaranteed to have removed all the kids.
@@ -356,12 +341,12 @@ function rmkidsSync (p, options) {
356
341
  // try really hard to delete stuff on windows, because it has a
357
342
  // PROFOUNDLY annoying habit of not closing handles promptly when
358
343
  // files are deleted, resulting in spurious ENOTEMPTY errors.
359
- var retries = isWindows ? 100 : 1
360
- var i = 0
344
+ const retries = isWindows ? 100 : 1
345
+ let i = 0
361
346
  do {
362
- var threw = true
347
+ let threw = true
363
348
  try {
364
- var ret = options.rmdirSync(p, options)
349
+ const ret = options.rmdirSync(p, options)
365
350
  threw = false
366
351
  return ret
367
352
  } finally {
@@ -370,3 +355,6 @@ function rmkidsSync (p, options) {
370
355
  }
371
356
  } while (true)
372
357
  }
358
+
359
+ module.exports = rimraf
360
+ rimraf.sync = rimrafSync