.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / node_modules / rimraf / rimraf.js
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)
9
10 var defaultGlobOpts = {
11   nosort: true,
12   silent: true
13 }
14
15 // for EMFILE handling
16 var timeout = 0
17
18 var isWindows = (process.platform === "win32")
19
20 function defaults (options) {
21   var methods = [
22     'unlink',
23     'chmod',
24     'stat',
25     'lstat',
26     'rmdir',
27     'readdir'
28   ]
29   methods.forEach(function(m) {
30     options[m] = options[m] || fs[m]
31     m = m + 'Sync'
32     options[m] = options[m] || fs[m]
33   })
34
35   options.maxBusyTries = options.maxBusyTries || 3
36   options.emfileWait = options.emfileWait || 1000
37   if (options.glob === false) {
38     options.disableGlob = true
39   }
40   options.disableGlob = options.disableGlob || false
41   options.glob = options.glob || defaultGlobOpts
42 }
43
44 function rimraf (p, options, cb) {
45   if (typeof options === 'function') {
46     cb = options
47     options = {}
48   }
49
50   assert(p, 'rimraf: missing path')
51   assert.equal(typeof p, 'string', 'rimraf: path should be a string')
52   assert.equal(typeof cb, 'function', 'rimraf: callback function required')
53   assert(options, 'rimraf: invalid options argument provided')
54   assert.equal(typeof options, 'object', 'rimraf: options should be object')
55
56   defaults(options)
57
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])
64
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) {
73     errState = errState || er
74     if (--n === 0)
75       cb(errState)
76   }
77
78   function afterGlob (er, results) {
79     if (er)
80       return cb(er)
81
82     n = results.length
83     if (n === 0)
84       return cb()
85
86     results.forEach(function (p) {
87       rimraf_(p, options, function CB (er) {
88         if (er) {
89           if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
90               busyTries < options.maxBusyTries) {
91             busyTries ++
92             var time = busyTries * 100
93             // try again, with the same exact callback as this one.
94             return setTimeout(function () {
95               rimraf_(p, options, CB)
96             }, time)
97           }
98
99           // this one won't happen if graceful-fs is used.
100           if (er.code === "EMFILE" && timeout < options.emfileWait) {
101             return setTimeout(function () {
102               rimraf_(p, options, CB)
103             }, timeout ++)
104           }
105
106           // already gone
107           if (er.code === "ENOENT") er = null
108         }
109
110         timeout = 0
111         next(er)
112       })
113     })
114   }
115 }
116
117 // Two possible strategies.
118 // 1. Assume it's a file.  unlink it, then do the dir stuff on EPERM or EISDIR
119 // 2. Assume it's a directory.  readdir, then do the file stuff on ENOTDIR
120 //
121 // Both result in an extra syscall when you guess wrong.  However, there
122 // are likely far more normal files in the world than directories.  This
123 // is based on the assumption that a the average number of files per
124 // directory is >= 1.
125 //
126 // If anyone ever complains about this, then I guess the strategy could
127 // be made configurable somehow.  But until then, YAGNI.
128 function rimraf_ (p, options, cb) {
129   assert(p)
130   assert(options)
131   assert(typeof cb === 'function')
132
133   // sunos lets the root user unlink directories, which is... weird.
134   // so we have to lstat here and make sure it's not a dir.
135   options.lstat(p, function (er, st) {
136     if (er && er.code === "ENOENT")
137       return cb(null)
138
139     // Windows can EPERM on stat.  Life is suffering.
140     if (er && er.code === "EPERM" && isWindows)
141       fixWinEPERM(p, options, er, cb)
142
143     if (st && st.isDirectory())
144       return rmdir(p, options, er, cb)
145
146     options.unlink(p, function (er) {
147       if (er) {
148         if (er.code === "ENOENT")
149           return cb(null)
150         if (er.code === "EPERM")
151           return (isWindows)
152             ? fixWinEPERM(p, options, er, cb)
153             : rmdir(p, options, er, cb)
154         if (er.code === "EISDIR")
155           return rmdir(p, options, er, cb)
156       }
157       return cb(er)
158     })
159   })
160 }
161
162 function fixWinEPERM (p, options, er, cb) {
163   assert(p)
164   assert(options)
165   assert(typeof cb === 'function')
166   if (er)
167     assert(er instanceof Error)
168
169   options.chmod(p, _0666, function (er2) {
170     if (er2)
171       cb(er2.code === "ENOENT" ? null : er)
172     else
173       options.stat(p, function(er3, stats) {
174         if (er3)
175           cb(er3.code === "ENOENT" ? null : er)
176         else if (stats.isDirectory())
177           rmdir(p, options, er, cb)
178         else
179           options.unlink(p, cb)
180       })
181   })
182 }
183
184 function fixWinEPERMSync (p, options, er) {
185   assert(p)
186   assert(options)
187   if (er)
188     assert(er instanceof Error)
189
190   try {
191     options.chmodSync(p, _0666)
192   } catch (er2) {
193     if (er2.code === "ENOENT")
194       return
195     else
196       throw er
197   }
198
199   try {
200     var stats = options.statSync(p)
201   } catch (er3) {
202     if (er3.code === "ENOENT")
203       return
204     else
205       throw er
206   }
207
208   if (stats.isDirectory())
209     rmdirSync(p, options, er)
210   else
211     options.unlinkSync(p)
212 }
213
214 function rmdir (p, options, originalEr, cb) {
215   assert(p)
216   assert(options)
217   if (originalEr)
218     assert(originalEr instanceof Error)
219   assert(typeof cb === 'function')
220
221   // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
222   // if we guessed wrong, and it's not a directory, then
223   // raise the original error.
224   options.rmdir(p, function (er) {
225     if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))
226       rmkids(p, options, cb)
227     else if (er && er.code === "ENOTDIR")
228       cb(originalEr)
229     else
230       cb(er)
231   })
232 }
233
234 function rmkids(p, options, cb) {
235   assert(p)
236   assert(options)
237   assert(typeof cb === 'function')
238
239   options.readdir(p, function (er, files) {
240     if (er)
241       return cb(er)
242     var n = files.length
243     if (n === 0)
244       return options.rmdir(p, cb)
245     var errState
246     files.forEach(function (f) {
247       rimraf(path.join(p, f), options, function (er) {
248         if (errState)
249           return
250         if (er)
251           return cb(errState = er)
252         if (--n === 0)
253           options.rmdir(p, cb)
254       })
255     })
256   })
257 }
258
259 // this looks simpler, and is strictly *faster*, but will
260 // tie up the JavaScript thread and fail on excessively
261 // deep directory trees.
262 function rimrafSync (p, options) {
263   options = options || {}
264   defaults(options)
265
266   assert(p, 'rimraf: missing path')
267   assert.equal(typeof p, 'string', 'rimraf: path should be a string')
268   assert(options, 'rimraf: missing options')
269   assert.equal(typeof options, 'object', 'rimraf: options should be object')
270
271   var results
272
273   if (options.disableGlob || !glob.hasMagic(p)) {
274     results = [p]
275   } else {
276     try {
277       options.lstatSync(p)
278       results = [p]
279     } catch (er) {
280       results = glob.sync(p, options.glob)
281     }
282   }
283
284   if (!results.length)
285     return
286
287   for (var i = 0; i < results.length; i++) {
288     var p = results[i]
289
290     try {
291       var st = options.lstatSync(p)
292     } catch (er) {
293       if (er.code === "ENOENT")
294         return
295
296       // Windows can EPERM on stat.  Life is suffering.
297       if (er.code === "EPERM" && isWindows)
298         fixWinEPERMSync(p, options, er)
299     }
300
301     try {
302       // sunos lets the root user unlink directories, which is... weird.
303       if (st && st.isDirectory())
304         rmdirSync(p, options, null)
305       else
306         options.unlinkSync(p)
307     } catch (er) {
308       if (er.code === "ENOENT")
309         return
310       if (er.code === "EPERM")
311         return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
312       if (er.code !== "EISDIR")
313         throw er
314
315       rmdirSync(p, options, er)
316     }
317   }
318 }
319
320 function rmdirSync (p, options, originalEr) {
321   assert(p)
322   assert(options)
323   if (originalEr)
324     assert(originalEr instanceof Error)
325
326   try {
327     options.rmdirSync(p)
328   } catch (er) {
329     if (er.code === "ENOENT")
330       return
331     if (er.code === "ENOTDIR")
332       throw originalEr
333     if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")
334       rmkidsSync(p, options)
335   }
336 }
337
338 function rmkidsSync (p, options) {
339   assert(p)
340   assert(options)
341   options.readdirSync(p).forEach(function (f) {
342     rimrafSync(path.join(p, f), options)
343   })
344
345   // We only end up here once we got ENOTEMPTY at least once, and
346   // at this point, we are guaranteed to have removed all the kids.
347   // So, we know that it won't be ENOENT or ENOTDIR or anything else.
348   // try really hard to delete stuff on windows, because it has a
349   // PROFOUNDLY annoying habit of not closing handles promptly when
350   // files are deleted, resulting in spurious ENOTEMPTY errors.
351   var retries = isWindows ? 100 : 1
352   var i = 0
353   do {
354     var threw = true
355     try {
356       var ret = options.rmdirSync(p, options)
357       threw = false
358       return ret
359     } finally {
360       if (++i < retries && threw)
361         continue
362     }
363   } while (true)
364 }