rimraf 2.6.2 → 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.
Files changed (3) hide show
  1. package/bin.js +41 -23
  2. package/package.json +6 -3
  3. package/rimraf.js +75 -71
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,17 +1,20 @@
1
1
  {
2
2
  "name": "rimraf",
3
- "version": "2.6.2",
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/)",
7
7
  "license": "ISC",
8
8
  "repository": "git://github.com/isaacs/rimraf.git",
9
9
  "scripts": {
10
+ "preversion": "npm test",
11
+ "postversion": "npm publish",
12
+ "postpublish": "git push origin --follow-tags",
10
13
  "test": "tap test/*.js"
11
14
  },
12
15
  "bin": "./bin.js",
13
16
  "dependencies": {
14
- "glob": "^7.0.5"
17
+ "glob": "^7.1.3"
15
18
  },
16
19
  "files": [
17
20
  "LICENSE",
@@ -21,6 +24,6 @@
21
24
  ],
22
25
  "devDependencies": {
23
26
  "mkdirp": "^0.5.1",
24
- "tap": "^10.1.2"
27
+ "tap": "^12.1.1"
25
28
  }
26
29
  }
package/rimraf.js CHANGED
@@ -1,24 +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")
7
- var glob = require("glob")
8
- var _0666 = parseInt('666', 8)
1
+ const assert = require("assert")
2
+ const path = require("path")
3
+ const fs = require("fs")
4
+ let glob = undefined
5
+ try {
6
+ glob = require("glob")
7
+ } catch (_err) {
8
+ // treat glob as optional.
9
+ }
9
10
 
10
- var defaultGlobOpts = {
11
+ const defaultGlobOpts = {
11
12
  nosort: true,
12
13
  silent: true
13
14
  }
14
15
 
15
16
  // for EMFILE handling
16
- var timeout = 0
17
+ let timeout = 0
17
18
 
18
- var isWindows = (process.platform === "win32")
19
+ const isWindows = (process.platform === "win32")
19
20
 
20
- function defaults (options) {
21
- var methods = [
21
+ const defaults = options => {
22
+ const methods = [
22
23
  'unlink',
23
24
  'chmod',
24
25
  'stat',
@@ -26,7 +27,7 @@ function defaults (options) {
26
27
  'rmdir',
27
28
  'readdir'
28
29
  ]
29
- methods.forEach(function(m) {
30
+ methods.forEach(m => {
30
31
  options[m] = options[m] || fs[m]
31
32
  m = m + 'Sync'
32
33
  options[m] = options[m] || fs[m]
@@ -37,11 +38,14 @@ function defaults (options) {
37
38
  if (options.glob === false) {
38
39
  options.disableGlob = true
39
40
  }
41
+ if (options.disableGlob !== true && glob === undefined) {
42
+ throw Error('glob dependency not found, set `options.disableGlob = true` if intentional')
43
+ }
40
44
  options.disableGlob = options.disableGlob || false
41
45
  options.glob = options.glob || defaultGlobOpts
42
46
  }
43
47
 
44
- function rimraf (p, options, cb) {
48
+ const rimraf = (p, options, cb) => {
45
49
  if (typeof options === 'function') {
46
50
  cb = options
47
51
  options = {}
@@ -55,27 +59,17 @@ function rimraf (p, options, cb) {
55
59
 
56
60
  defaults(options)
57
61
 
58
- var busyTries = 0
59
- var errState = null
60
- var n = 0
61
-
62
- if (options.disableGlob || !glob.hasMagic(p))
63
- return afterGlob(null, [p])
62
+ let busyTries = 0
63
+ let errState = null
64
+ let n = 0
64
65
 
65
- options.lstat(p, function (er, stat) {
66
- if (!er)
67
- return afterGlob(null, [p])
68
-
69
- glob(p, options.glob, afterGlob)
70
- })
71
-
72
- function next (er) {
66
+ const next = (er) => {
73
67
  errState = errState || er
74
68
  if (--n === 0)
75
69
  cb(errState)
76
70
  }
77
71
 
78
- function afterGlob (er, results) {
72
+ const afterGlob = (er, results) => {
79
73
  if (er)
80
74
  return cb(er)
81
75
 
@@ -83,24 +77,19 @@ function rimraf (p, options, cb) {
83
77
  if (n === 0)
84
78
  return cb()
85
79
 
86
- results.forEach(function (p) {
87
- rimraf_(p, options, function CB (er) {
80
+ results.forEach(p => {
81
+ const CB = (er) => {
88
82
  if (er) {
89
83
  if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
90
84
  busyTries < options.maxBusyTries) {
91
85
  busyTries ++
92
- var time = busyTries * 100
93
86
  // try again, with the same exact callback as this one.
94
- return setTimeout(function () {
95
- rimraf_(p, options, CB)
96
- }, time)
87
+ return setTimeout(() => rimraf_(p, options, CB), busyTries * 100)
97
88
  }
98
89
 
99
90
  // this one won't happen if graceful-fs is used.
100
91
  if (er.code === "EMFILE" && timeout < options.emfileWait) {
101
- return setTimeout(function () {
102
- rimraf_(p, options, CB)
103
- }, timeout ++)
92
+ return setTimeout(() => rimraf_(p, options, CB), timeout ++)
104
93
  }
105
94
 
106
95
  // already gone
@@ -109,9 +98,21 @@ function rimraf (p, options, cb) {
109
98
 
110
99
  timeout = 0
111
100
  next(er)
112
- })
101
+ }
102
+ rimraf_(p, options, CB)
113
103
  })
114
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
+
115
116
  }
116
117
 
117
118
  // Two possible strategies.
@@ -125,14 +126,14 @@ function rimraf (p, options, cb) {
125
126
  //
126
127
  // If anyone ever complains about this, then I guess the strategy could
127
128
  // be made configurable somehow. But until then, YAGNI.
128
- function rimraf_ (p, options, cb) {
129
+ const rimraf_ = (p, options, cb) => {
129
130
  assert(p)
130
131
  assert(options)
131
132
  assert(typeof cb === 'function')
132
133
 
133
134
  // sunos lets the root user unlink directories, which is... weird.
134
135
  // so we have to lstat here and make sure it's not a dir.
135
- options.lstat(p, function (er, st) {
136
+ options.lstat(p, (er, st) => {
136
137
  if (er && er.code === "ENOENT")
137
138
  return cb(null)
138
139
 
@@ -143,7 +144,7 @@ function rimraf_ (p, options, cb) {
143
144
  if (st && st.isDirectory())
144
145
  return rmdir(p, options, er, cb)
145
146
 
146
- options.unlink(p, function (er) {
147
+ options.unlink(p, er => {
147
148
  if (er) {
148
149
  if (er.code === "ENOENT")
149
150
  return cb(null)
@@ -159,18 +160,18 @@ function rimraf_ (p, options, cb) {
159
160
  })
160
161
  }
161
162
 
162
- function fixWinEPERM (p, options, er, cb) {
163
+ const fixWinEPERM = (p, options, er, cb) => {
163
164
  assert(p)
164
165
  assert(options)
165
166
  assert(typeof cb === 'function')
166
167
  if (er)
167
168
  assert(er instanceof Error)
168
169
 
169
- options.chmod(p, _0666, function (er2) {
170
+ options.chmod(p, 0o666, er2 => {
170
171
  if (er2)
171
172
  cb(er2.code === "ENOENT" ? null : er)
172
173
  else
173
- options.stat(p, function(er3, stats) {
174
+ options.stat(p, (er3, stats) => {
174
175
  if (er3)
175
176
  cb(er3.code === "ENOENT" ? null : er)
176
177
  else if (stats.isDirectory())
@@ -181,14 +182,14 @@ function fixWinEPERM (p, options, er, cb) {
181
182
  })
182
183
  }
183
184
 
184
- function fixWinEPERMSync (p, options, er) {
185
+ const fixWinEPERMSync = (p, options, er) => {
185
186
  assert(p)
186
187
  assert(options)
187
188
  if (er)
188
189
  assert(er instanceof Error)
189
190
 
190
191
  try {
191
- options.chmodSync(p, _0666)
192
+ options.chmodSync(p, 0o666)
192
193
  } catch (er2) {
193
194
  if (er2.code === "ENOENT")
194
195
  return
@@ -196,8 +197,9 @@ function fixWinEPERMSync (p, options, er) {
196
197
  throw er
197
198
  }
198
199
 
200
+ let stats
199
201
  try {
200
- var stats = options.statSync(p)
202
+ stats = options.statSync(p)
201
203
  } catch (er3) {
202
204
  if (er3.code === "ENOENT")
203
205
  return
@@ -211,7 +213,7 @@ function fixWinEPERMSync (p, options, er) {
211
213
  options.unlinkSync(p)
212
214
  }
213
215
 
214
- function rmdir (p, options, originalEr, cb) {
216
+ const rmdir = (p, options, originalEr, cb) => {
215
217
  assert(p)
216
218
  assert(options)
217
219
  if (originalEr)
@@ -221,7 +223,7 @@ function rmdir (p, options, originalEr, cb) {
221
223
  // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
222
224
  // if we guessed wrong, and it's not a directory, then
223
225
  // raise the original error.
224
- options.rmdir(p, function (er) {
226
+ options.rmdir(p, er => {
225
227
  if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))
226
228
  rmkids(p, options, cb)
227
229
  else if (er && er.code === "ENOTDIR")
@@ -231,20 +233,20 @@ function rmdir (p, options, originalEr, cb) {
231
233
  })
232
234
  }
233
235
 
234
- function rmkids(p, options, cb) {
236
+ const rmkids = (p, options, cb) => {
235
237
  assert(p)
236
238
  assert(options)
237
239
  assert(typeof cb === 'function')
238
240
 
239
- options.readdir(p, function (er, files) {
241
+ options.readdir(p, (er, files) => {
240
242
  if (er)
241
243
  return cb(er)
242
- var n = files.length
244
+ let n = files.length
243
245
  if (n === 0)
244
246
  return options.rmdir(p, cb)
245
- var errState
246
- files.forEach(function (f) {
247
- rimraf(path.join(p, f), options, function (er) {
247
+ let errState
248
+ files.forEach(f => {
249
+ rimraf(path.join(p, f), options, er => {
248
250
  if (errState)
249
251
  return
250
252
  if (er)
@@ -259,7 +261,7 @@ function rmkids(p, options, cb) {
259
261
  // this looks simpler, and is strictly *faster*, but will
260
262
  // tie up the JavaScript thread and fail on excessively
261
263
  // deep directory trees.
262
- function rimrafSync (p, options) {
264
+ const rimrafSync = (p, options) => {
263
265
  options = options || {}
264
266
  defaults(options)
265
267
 
@@ -268,7 +270,7 @@ function rimrafSync (p, options) {
268
270
  assert(options, 'rimraf: missing options')
269
271
  assert.equal(typeof options, 'object', 'rimraf: options should be object')
270
272
 
271
- var results
273
+ let results
272
274
 
273
275
  if (options.disableGlob || !glob.hasMagic(p)) {
274
276
  results = [p]
@@ -284,11 +286,12 @@ function rimrafSync (p, options) {
284
286
  if (!results.length)
285
287
  return
286
288
 
287
- for (var i = 0; i < results.length; i++) {
288
- var p = results[i]
289
+ for (let i = 0; i < results.length; i++) {
290
+ const p = results[i]
289
291
 
292
+ let st
290
293
  try {
291
- var st = options.lstatSync(p)
294
+ st = options.lstatSync(p)
292
295
  } catch (er) {
293
296
  if (er.code === "ENOENT")
294
297
  return
@@ -317,7 +320,7 @@ function rimrafSync (p, options) {
317
320
  }
318
321
  }
319
322
 
320
- function rmdirSync (p, options, originalEr) {
323
+ const rmdirSync = (p, options, originalEr) => {
321
324
  assert(p)
322
325
  assert(options)
323
326
  if (originalEr)
@@ -335,12 +338,10 @@ function rmdirSync (p, options, originalEr) {
335
338
  }
336
339
  }
337
340
 
338
- function rmkidsSync (p, options) {
341
+ const rmkidsSync = (p, options) => {
339
342
  assert(p)
340
343
  assert(options)
341
- options.readdirSync(p).forEach(function (f) {
342
- rimrafSync(path.join(p, f), options)
343
- })
344
+ options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))
344
345
 
345
346
  // We only end up here once we got ENOTEMPTY at least once, and
346
347
  // at this point, we are guaranteed to have removed all the kids.
@@ -348,12 +349,12 @@ function rmkidsSync (p, options) {
348
349
  // try really hard to delete stuff on windows, because it has a
349
350
  // PROFOUNDLY annoying habit of not closing handles promptly when
350
351
  // files are deleted, resulting in spurious ENOTEMPTY errors.
351
- var retries = isWindows ? 100 : 1
352
- var i = 0
352
+ const retries = isWindows ? 100 : 1
353
+ let i = 0
353
354
  do {
354
- var threw = true
355
+ let threw = true
355
356
  try {
356
- var ret = options.rmdirSync(p, options)
357
+ const ret = options.rmdirSync(p, options)
357
358
  threw = false
358
359
  return ret
359
360
  } finally {
@@ -362,3 +363,6 @@ function rmkidsSync (p, options) {
362
363
  }
363
364
  } while (true)
364
365
  }
366
+
367
+ module.exports = rimraf
368
+ rimraf.sync = rimrafSync