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 | module.exports = glob
|
42 |
|
43 | var fs = require('fs')
|
44 | var rp = require('fs.realpath')
|
45 | var minimatch = require('minimatch')
|
46 | var Minimatch = minimatch.Minimatch
|
47 | var inherits = require('inherits')
|
48 | var EE = require('events').EventEmitter
|
49 | var path = require('path')
|
50 | var assert = require('assert')
|
51 | var isAbsolute = require('path-is-absolute')
|
52 | var globSync = require('./sync.js')
|
53 | var common = require('./common.js')
|
54 | var alphasort = common.alphasort
|
55 | var alphasorti = common.alphasorti
|
56 | var setopts = common.setopts
|
57 | var ownProp = common.ownProp
|
58 | var inflight = require('inflight')
|
59 | var util = require('util')
|
60 | var childrenIgnored = common.childrenIgnored
|
61 | var isIgnored = common.isIgnored
|
62 |
|
63 | var once = require('once')
|
64 |
|
65 | function glob (pattern, options, cb) {
|
66 | if (typeof options === 'function') cb = options, options = {}
|
67 | if (!options) options = {}
|
68 |
|
69 | if (options.sync) {
|
70 | if (cb)
|
71 | throw new TypeError('callback provided to sync glob')
|
72 | return globSync(pattern, options)
|
73 | }
|
74 |
|
75 | return new Glob(pattern, options, cb)
|
76 | }
|
77 |
|
78 | glob.sync = globSync
|
79 | var GlobSync = glob.GlobSync = globSync.GlobSync
|
80 |
|
81 |
|
82 | glob.glob = glob
|
83 |
|
84 | function extend (origin, add) {
|
85 | if (add === null || typeof add !== 'object') {
|
86 | return origin
|
87 | }
|
88 |
|
89 | var keys = Object.keys(add)
|
90 | var i = keys.length
|
91 | while (i--) {
|
92 | origin[keys[i]] = add[keys[i]]
|
93 | }
|
94 | return origin
|
95 | }
|
96 |
|
97 | glob.hasMagic = function (pattern, options_) {
|
98 | var options = extend({}, options_)
|
99 | options.noprocess = true
|
100 |
|
101 | var g = new Glob(pattern, options)
|
102 | var set = g.minimatch.set
|
103 |
|
104 | if (!pattern)
|
105 | return false
|
106 |
|
107 | if (set.length > 1)
|
108 | return true
|
109 |
|
110 | for (var j = 0; j < set[0].length; j++) {
|
111 | if (typeof set[0][j] !== 'string')
|
112 | return true
|
113 | }
|
114 |
|
115 | return false
|
116 | }
|
117 |
|
118 | glob.Glob = Glob
|
119 | inherits(Glob, EE)
|
120 | function Glob (pattern, options, cb) {
|
121 | if (typeof options === 'function') {
|
122 | cb = options
|
123 | options = null
|
124 | }
|
125 |
|
126 | if (options && options.sync) {
|
127 | if (cb)
|
128 | throw new TypeError('callback provided to sync glob')
|
129 | return new GlobSync(pattern, options)
|
130 | }
|
131 |
|
132 | if (!(this instanceof Glob))
|
133 | return new Glob(pattern, options, cb)
|
134 |
|
135 | setopts(this, pattern, options)
|
136 | this._didRealPath = false
|
137 |
|
138 |
|
139 | var n = this.minimatch.set.length
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 | this.matches = new Array(n)
|
146 |
|
147 | if (typeof cb === 'function') {
|
148 | cb = once(cb)
|
149 | this.on('error', cb)
|
150 | this.on('end', function (matches) {
|
151 | cb(null, matches)
|
152 | })
|
153 | }
|
154 |
|
155 | var self = this
|
156 | this._processing = 0
|
157 |
|
158 | this._emitQueue = []
|
159 | this._processQueue = []
|
160 | this.paused = false
|
161 |
|
162 | if (this.noprocess)
|
163 | return this
|
164 |
|
165 | if (n === 0)
|
166 | return done()
|
167 |
|
168 | var sync = true
|
169 | for (var i = 0; i < n; i ++) {
|
170 | this._process(this.minimatch.set[i], i, false, done)
|
171 | }
|
172 | sync = false
|
173 |
|
174 | function done () {
|
175 | --self._processing
|
176 | if (self._processing <= 0) {
|
177 | if (sync) {
|
178 | process.nextTick(function () {
|
179 | self._finish()
|
180 | })
|
181 | } else {
|
182 | self._finish()
|
183 | }
|
184 | }
|
185 | }
|
186 | }
|
187 |
|
188 | Glob.prototype._finish = function () {
|
189 | assert(this instanceof Glob)
|
190 | if (this.aborted)
|
191 | return
|
192 |
|
193 | if (this.realpath && !this._didRealpath)
|
194 | return this._realpath()
|
195 |
|
196 | common.finish(this)
|
197 | this.emit('end', this.found)
|
198 | }
|
199 |
|
200 | Glob.prototype._realpath = function () {
|
201 | if (this._didRealpath)
|
202 | return
|
203 |
|
204 | this._didRealpath = true
|
205 |
|
206 | var n = this.matches.length
|
207 | if (n === 0)
|
208 | return this._finish()
|
209 |
|
210 | var self = this
|
211 | for (var i = 0; i < this.matches.length; i++)
|
212 | this._realpathSet(i, next)
|
213 |
|
214 | function next () {
|
215 | if (--n === 0)
|
216 | self._finish()
|
217 | }
|
218 | }
|
219 |
|
220 | Glob.prototype._realpathSet = function (index, cb) {
|
221 | var matchset = this.matches[index]
|
222 | if (!matchset)
|
223 | return cb()
|
224 |
|
225 | var found = Object.keys(matchset)
|
226 | var self = this
|
227 | var n = found.length
|
228 |
|
229 | if (n === 0)
|
230 | return cb()
|
231 |
|
232 | var set = this.matches[index] = Object.create(null)
|
233 | found.forEach(function (p, i) {
|
234 |
|
235 |
|
236 |
|
237 | p = self._makeAbs(p)
|
238 | rp.realpath(p, self.realpathCache, function (er, real) {
|
239 | if (!er)
|
240 | set[real] = true
|
241 | else if (er.syscall === 'stat')
|
242 | set[p] = true
|
243 | else
|
244 | self.emit('error', er) // srsly wtf right here
|
245 |
|
246 | if (--n === 0) {
|
247 | self.matches[index] = set
|
248 | cb()
|
249 | }
|
250 | })
|
251 | })
|
252 | }
|
253 |
|
254 | Glob.prototype._mark = function (p) {
|
255 | return common.mark(this, p)
|
256 | }
|
257 |
|
258 | Glob.prototype._makeAbs = function (f) {
|
259 | return common.makeAbs(this, f)
|
260 | }
|
261 |
|
262 | Glob.prototype.abort = function () {
|
263 | this.aborted = true
|
264 | this.emit('abort')
|
265 | }
|
266 |
|
267 | Glob.prototype.pause = function () {
|
268 | if (!this.paused) {
|
269 | this.paused = true
|
270 | this.emit('pause')
|
271 | }
|
272 | }
|
273 |
|
274 | Glob.prototype.resume = function () {
|
275 | if (this.paused) {
|
276 | this.emit('resume')
|
277 | this.paused = false
|
278 | if (this._emitQueue.length) {
|
279 | var eq = this._emitQueue.slice(0)
|
280 | this._emitQueue.length = 0
|
281 | for (var i = 0; i < eq.length; i ++) {
|
282 | var e = eq[i]
|
283 | this._emitMatch(e[0], e[1])
|
284 | }
|
285 | }
|
286 | if (this._processQueue.length) {
|
287 | var pq = this._processQueue.slice(0)
|
288 | this._processQueue.length = 0
|
289 | for (var i = 0; i < pq.length; i ++) {
|
290 | var p = pq[i]
|
291 | this._processing--
|
292 | this._process(p[0], p[1], p[2], p[3])
|
293 | }
|
294 | }
|
295 | }
|
296 | }
|
297 |
|
298 | Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
|
299 | assert(this instanceof Glob)
|
300 | assert(typeof cb === 'function')
|
301 |
|
302 | if (this.aborted)
|
303 | return
|
304 |
|
305 | this._processing++
|
306 | if (this.paused) {
|
307 | this._processQueue.push([pattern, index, inGlobStar, cb])
|
308 | return
|
309 | }
|
310 |
|
311 |
|
312 |
|
313 |
|
314 | var n = 0
|
315 | while (typeof pattern[n] === 'string') {
|
316 | n ++
|
317 | }
|
318 |
|
319 |
|
320 |
|
321 | var prefix
|
322 | switch (n) {
|
323 |
|
324 | case pattern.length:
|
325 | this._processSimple(pattern.join('/'), index, cb)
|
326 | return
|
327 |
|
328 | case 0:
|
329 |
|
330 |
|
331 | prefix = null
|
332 | break
|
333 |
|
334 | default:
|
335 |
|
336 |
|
337 |
|
338 | prefix = pattern.slice(0, n).join('/')
|
339 | break
|
340 | }
|
341 |
|
342 | var remain = pattern.slice(n)
|
343 |
|
344 |
|
345 | var read
|
346 | if (prefix === null)
|
347 | read = '.'
|
348 | else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
|
349 | if (!prefix || !isAbsolute(prefix))
|
350 | prefix = '/' + prefix
|
351 | read = prefix
|
352 | } else
|
353 | read = prefix
|
354 |
|
355 | var abs = this._makeAbs(read)
|
356 |
|
357 |
|
358 | if (childrenIgnored(this, read))
|
359 | return cb()
|
360 |
|
361 | var isGlobStar = remain[0] === minimatch.GLOBSTAR
|
362 | if (isGlobStar)
|
363 | this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
|
364 | else
|
365 | this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
|
366 | }
|
367 |
|
368 | Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
|
369 | var self = this
|
370 | this._readdir(abs, inGlobStar, function (er, entries) {
|
371 | return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
|
372 | })
|
373 | }
|
374 |
|
375 | Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
|
376 |
|
377 |
|
378 | if (!entries)
|
379 | return cb()
|
380 |
|
381 |
|
382 |
|
383 | var pn = remain[0]
|
384 | var negate = !!this.minimatch.negate
|
385 | var rawGlob = pn._glob
|
386 | var dotOk = this.dot || rawGlob.charAt(0) === '.'
|
387 |
|
388 | var matchedEntries = []
|
389 | for (var i = 0; i < entries.length; i++) {
|
390 | var e = entries[i]
|
391 | if (e.charAt(0) !== '.' || dotOk) {
|
392 | var m
|
393 | if (negate && !prefix) {
|
394 | m = !e.match(pn)
|
395 | } else {
|
396 | m = e.match(pn)
|
397 | }
|
398 | if (m)
|
399 | matchedEntries.push(e)
|
400 | }
|
401 | }
|
402 |
|
403 |
|
404 |
|
405 | var len = matchedEntries.length
|
406 |
|
407 | if (len === 0)
|
408 | return cb()
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 |
|
415 | if (remain.length === 1 && !this.mark && !this.stat) {
|
416 | if (!this.matches[index])
|
417 | this.matches[index] = Object.create(null)
|
418 |
|
419 | for (var i = 0; i < len; i ++) {
|
420 | var e = matchedEntries[i]
|
421 | if (prefix) {
|
422 | if (prefix !== '/')
|
423 | e = prefix + '/' + e
|
424 | else
|
425 | e = prefix + e
|
426 | }
|
427 |
|
428 | if (e.charAt(0) === '/' && !this.nomount) {
|
429 | e = path.join(this.root, e)
|
430 | }
|
431 | this._emitMatch(index, e)
|
432 | }
|
433 |
|
434 | return cb()
|
435 | }
|
436 |
|
437 |
|
438 |
|
439 | remain.shift()
|
440 | for (var i = 0; i < len; i ++) {
|
441 | var e = matchedEntries[i]
|
442 | var newPattern
|
443 | if (prefix) {
|
444 | if (prefix !== '/')
|
445 | e = prefix + '/' + e
|
446 | else
|
447 | e = prefix + e
|
448 | }
|
449 | this._process([e].concat(remain), index, inGlobStar, cb)
|
450 | }
|
451 | cb()
|
452 | }
|
453 |
|
454 | Glob.prototype._emitMatch = function (index, e) {
|
455 | if (this.aborted)
|
456 | return
|
457 |
|
458 | if (isIgnored(this, e))
|
459 | return
|
460 |
|
461 | if (this.paused) {
|
462 | this._emitQueue.push([index, e])
|
463 | return
|
464 | }
|
465 |
|
466 | var abs = isAbsolute(e) ? e : this._makeAbs(e)
|
467 |
|
468 | if (this.mark)
|
469 | e = this._mark(e)
|
470 |
|
471 | if (this.absolute)
|
472 | e = abs
|
473 |
|
474 | if (this.matches[index][e])
|
475 | return
|
476 |
|
477 | if (this.nodir) {
|
478 | var c = this.cache[abs]
|
479 | if (c === 'DIR' || Array.isArray(c))
|
480 | return
|
481 | }
|
482 |
|
483 | this.matches[index][e] = true
|
484 |
|
485 | var st = this.statCache[abs]
|
486 | if (st)
|
487 | this.emit('stat', e, st)
|
488 |
|
489 | this.emit('match', e)
|
490 | }
|
491 |
|
492 | Glob.prototype._readdirInGlobStar = function (abs, cb) {
|
493 | if (this.aborted)
|
494 | return
|
495 |
|
496 |
|
497 |
|
498 | if (this.follow)
|
499 | return this._readdir(abs, false, cb)
|
500 |
|
501 | var lstatkey = 'lstat\0' + abs
|
502 | var self = this
|
503 | var lstatcb = inflight(lstatkey, lstatcb_)
|
504 |
|
505 | if (lstatcb)
|
506 | fs.lstat(abs, lstatcb)
|
507 |
|
508 | function lstatcb_ (er, lstat) {
|
509 | if (er && er.code === 'ENOENT')
|
510 | return cb()
|
511 |
|
512 | var isSym = lstat && lstat.isSymbolicLink()
|
513 | self.symlinks[abs] = isSym
|
514 |
|
515 |
|
516 |
|
517 | if (!isSym && lstat && !lstat.isDirectory()) {
|
518 | self.cache[abs] = 'FILE'
|
519 | cb()
|
520 | } else
|
521 | self._readdir(abs, false, cb)
|
522 | }
|
523 | }
|
524 |
|
525 | Glob.prototype._readdir = function (abs, inGlobStar, cb) {
|
526 | if (this.aborted)
|
527 | return
|
528 |
|
529 | cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
|
530 | if (!cb)
|
531 | return
|
532 |
|
533 |
|
534 | if (inGlobStar && !ownProp(this.symlinks, abs))
|
535 | return this._readdirInGlobStar(abs, cb)
|
536 |
|
537 | if (ownProp(this.cache, abs)) {
|
538 | var c = this.cache[abs]
|
539 | if (!c || c === 'FILE')
|
540 | return cb()
|
541 |
|
542 | if (Array.isArray(c))
|
543 | return cb(null, c)
|
544 | }
|
545 |
|
546 | var self = this
|
547 | fs.readdir(abs, readdirCb(this, abs, cb))
|
548 | }
|
549 |
|
550 | function readdirCb (self, abs, cb) {
|
551 | return function (er, entries) {
|
552 | if (er)
|
553 | self._readdirError(abs, er, cb)
|
554 | else
|
555 | self._readdirEntries(abs, entries, cb)
|
556 | }
|
557 | }
|
558 |
|
559 | Glob.prototype._readdirEntries = function (abs, entries, cb) {
|
560 | if (this.aborted)
|
561 | return
|
562 |
|
563 |
|
564 |
|
565 |
|
566 | if (!this.mark && !this.stat) {
|
567 | for (var i = 0; i < entries.length; i ++) {
|
568 | var e = entries[i]
|
569 | if (abs === '/')
|
570 | e = abs + e
|
571 | else
|
572 | e = abs + '/' + e
|
573 | this.cache[e] = true
|
574 | }
|
575 | }
|
576 |
|
577 | this.cache[abs] = entries
|
578 | return cb(null, entries)
|
579 | }
|
580 |
|
581 | Glob.prototype._readdirError = function (f, er, cb) {
|
582 | if (this.aborted)
|
583 | return
|
584 |
|
585 |
|
586 | switch (er.code) {
|
587 | case 'ENOTSUP':
|
588 | case 'ENOTDIR':
|
589 | var abs = this._makeAbs(f)
|
590 | this.cache[abs] = 'FILE'
|
591 | if (abs === this.cwdAbs) {
|
592 | var error = new Error(er.code + ' invalid cwd ' + this.cwd)
|
593 | error.path = this.cwd
|
594 | error.code = er.code
|
595 | this.emit('error', error)
|
596 | this.abort()
|
597 | }
|
598 | break
|
599 |
|
600 | case 'ENOENT':
|
601 | case 'ELOOP':
|
602 | case 'ENAMETOOLONG':
|
603 | case 'UNKNOWN':
|
604 | this.cache[this._makeAbs(f)] = false
|
605 | break
|
606 |
|
607 | default:
|
608 | this.cache[this._makeAbs(f)] = false
|
609 | if (this.strict) {
|
610 | this.emit('error', er)
|
611 |
|
612 |
|
613 | this.abort()
|
614 | }
|
615 | if (!this.silent)
|
616 | console.error('glob error', er)
|
617 | break
|
618 | }
|
619 |
|
620 | return cb()
|
621 | }
|
622 |
|
623 | Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
|
624 | var self = this
|
625 | this._readdir(abs, inGlobStar, function (er, entries) {
|
626 | self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
|
627 | })
|
628 | }
|
629 |
|
630 |
|
631 | Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
|
632 |
|
633 |
|
634 |
|
635 |
|
636 | if (!entries)
|
637 | return cb()
|
638 |
|
639 |
|
640 |
|
641 | var remainWithoutGlobStar = remain.slice(1)
|
642 | var gspref = prefix ? [ prefix ] : []
|
643 | var noGlobStar = gspref.concat(remainWithoutGlobStar)
|
644 |
|
645 |
|
646 | this._process(noGlobStar, index, false, cb)
|
647 |
|
648 | var isSym = this.symlinks[abs]
|
649 | var len = entries.length
|
650 |
|
651 |
|
652 | if (isSym && inGlobStar)
|
653 | return cb()
|
654 |
|
655 | for (var i = 0; i < len; i++) {
|
656 | var e = entries[i]
|
657 | if (e.charAt(0) === '.' && !this.dot)
|
658 | continue
|
659 |
|
660 |
|
661 | var instead = gspref.concat(entries[i], remainWithoutGlobStar)
|
662 | this._process(instead, index, true, cb)
|
663 |
|
664 | var below = gspref.concat(entries[i], remain)
|
665 | this._process(below, index, true, cb)
|
666 | }
|
667 |
|
668 | cb()
|
669 | }
|
670 |
|
671 | Glob.prototype._processSimple = function (prefix, index, cb) {
|
672 |
|
673 |
|
674 | var self = this
|
675 | this._stat(prefix, function (er, exists) {
|
676 | self._processSimple2(prefix, index, er, exists, cb)
|
677 | })
|
678 | }
|
679 | Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
|
680 |
|
681 |
|
682 |
|
683 | if (!this.matches[index])
|
684 | this.matches[index] = Object.create(null)
|
685 |
|
686 |
|
687 | if (!exists)
|
688 | return cb()
|
689 |
|
690 | if (prefix && isAbsolute(prefix) && !this.nomount) {
|
691 | var trail = /[\/\\]$/.test(prefix)
|
692 | if (prefix.charAt(0) === '/') {
|
693 | prefix = path.join(this.root, prefix)
|
694 | } else {
|
695 | prefix = path.resolve(this.root, prefix)
|
696 | if (trail)
|
697 | prefix += '/'
|
698 | }
|
699 | }
|
700 |
|
701 | if (process.platform === 'win32')
|
702 | prefix = prefix.replace(/\\/g, '/')
|
703 |
|
704 |
|
705 | this._emitMatch(index, prefix)
|
706 | cb()
|
707 | }
|
708 |
|
709 |
|
710 | Glob.prototype._stat = function (f, cb) {
|
711 | var abs = this._makeAbs(f)
|
712 | var needDir = f.slice(-1) === '/'
|
713 |
|
714 | if (f.length > this.maxLength)
|
715 | return cb()
|
716 |
|
717 | if (!this.stat && ownProp(this.cache, abs)) {
|
718 | var c = this.cache[abs]
|
719 |
|
720 | if (Array.isArray(c))
|
721 | c = 'DIR'
|
722 |
|
723 |
|
724 | if (!needDir || c === 'DIR')
|
725 | return cb(null, c)
|
726 |
|
727 | if (needDir && c === 'FILE')
|
728 | return cb()
|
729 |
|
730 |
|
731 |
|
732 | }
|
733 |
|
734 | var exists
|
735 | var stat = this.statCache[abs]
|
736 | if (stat !== undefined) {
|
737 | if (stat === false)
|
738 | return cb(null, stat)
|
739 | else {
|
740 | var type = stat.isDirectory() ? 'DIR' : 'FILE'
|
741 | if (needDir && type === 'FILE')
|
742 | return cb()
|
743 | else
|
744 | return cb(null, type, stat)
|
745 | }
|
746 | }
|
747 |
|
748 | var self = this
|
749 | var statcb = inflight('stat\0' + abs, lstatcb_)
|
750 | if (statcb)
|
751 | fs.lstat(abs, statcb)
|
752 |
|
753 | function lstatcb_ (er, lstat) {
|
754 | if (lstat && lstat.isSymbolicLink()) {
|
755 |
|
756 |
|
757 | return fs.stat(abs, function (er, stat) {
|
758 | if (er)
|
759 | self._stat2(f, abs, null, lstat, cb)
|
760 | else
|
761 | self._stat2(f, abs, er, stat, cb)
|
762 | })
|
763 | } else {
|
764 | self._stat2(f, abs, er, lstat, cb)
|
765 | }
|
766 | }
|
767 | }
|
768 |
|
769 | Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
|
770 | if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
|
771 | this.statCache[abs] = false
|
772 | return cb()
|
773 | }
|
774 |
|
775 | var needDir = f.slice(-1) === '/'
|
776 | this.statCache[abs] = stat
|
777 |
|
778 | if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
|
779 | return cb(null, false, stat)
|
780 |
|
781 | var c = true
|
782 | if (stat)
|
783 | c = stat.isDirectory() ? 'DIR' : 'FILE'
|
784 | this.cache[abs] = this.cache[abs] || c
|
785 |
|
786 | if (needDir && c === 'FILE')
|
787 | return cb()
|
788 |
|
789 | return cb(null, c, stat)
|
790 | }
|