Initial commit
[yaffs-website] / node_modules / minimatch / minimatch.js
1 module.exports = minimatch
2 minimatch.Minimatch = Minimatch
3
4 var path = { sep: '/' }
5 try {
6   path = require('path')
7 } catch (er) {}
8
9 var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
10 var expand = require('brace-expansion')
11
12 var plTypes = {
13   '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
14   '?': { open: '(?:', close: ')?' },
15   '+': { open: '(?:', close: ')+' },
16   '*': { open: '(?:', close: ')*' },
17   '@': { open: '(?:', close: ')' }
18 }
19
20 // any single thing other than /
21 // don't need to escape / when using new RegExp()
22 var qmark = '[^/]'
23
24 // * => any number of characters
25 var star = qmark + '*?'
26
27 // ** when dots are allowed.  Anything goes, except .. and .
28 // not (^ or / followed by one or two dots followed by $ or /),
29 // followed by anything, any number of times.
30 var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
31
32 // not a ^ or / followed by a dot,
33 // followed by anything, any number of times.
34 var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
35
36 // characters that need to be escaped in RegExp.
37 var reSpecials = charSet('().*{}+?[]^$\\!')
38
39 // "abc" -> { a:true, b:true, c:true }
40 function charSet (s) {
41   return s.split('').reduce(function (set, c) {
42     set[c] = true
43     return set
44   }, {})
45 }
46
47 // normalizes slashes.
48 var slashSplit = /\/+/
49
50 minimatch.filter = filter
51 function filter (pattern, options) {
52   options = options || {}
53   return function (p, i, list) {
54     return minimatch(p, pattern, options)
55   }
56 }
57
58 function ext (a, b) {
59   a = a || {}
60   b = b || {}
61   var t = {}
62   Object.keys(b).forEach(function (k) {
63     t[k] = b[k]
64   })
65   Object.keys(a).forEach(function (k) {
66     t[k] = a[k]
67   })
68   return t
69 }
70
71 minimatch.defaults = function (def) {
72   if (!def || !Object.keys(def).length) return minimatch
73
74   var orig = minimatch
75
76   var m = function minimatch (p, pattern, options) {
77     return orig.minimatch(p, pattern, ext(def, options))
78   }
79
80   m.Minimatch = function Minimatch (pattern, options) {
81     return new orig.Minimatch(pattern, ext(def, options))
82   }
83
84   return m
85 }
86
87 Minimatch.defaults = function (def) {
88   if (!def || !Object.keys(def).length) return Minimatch
89   return minimatch.defaults(def).Minimatch
90 }
91
92 function minimatch (p, pattern, options) {
93   if (typeof pattern !== 'string') {
94     throw new TypeError('glob pattern string required')
95   }
96
97   if (!options) options = {}
98
99   // shortcut: comments match nothing.
100   if (!options.nocomment && pattern.charAt(0) === '#') {
101     return false
102   }
103
104   // "" only matches ""
105   if (pattern.trim() === '') return p === ''
106
107   return new Minimatch(pattern, options).match(p)
108 }
109
110 function Minimatch (pattern, options) {
111   if (!(this instanceof Minimatch)) {
112     return new Minimatch(pattern, options)
113   }
114
115   if (typeof pattern !== 'string') {
116     throw new TypeError('glob pattern string required')
117   }
118
119   if (!options) options = {}
120   pattern = pattern.trim()
121
122   // windows support: need to use /, not \
123   if (path.sep !== '/') {
124     pattern = pattern.split(path.sep).join('/')
125   }
126
127   this.options = options
128   this.set = []
129   this.pattern = pattern
130   this.regexp = null
131   this.negate = false
132   this.comment = false
133   this.empty = false
134
135   // make the set of regexps etc.
136   this.make()
137 }
138
139 Minimatch.prototype.debug = function () {}
140
141 Minimatch.prototype.make = make
142 function make () {
143   // don't do it more than once.
144   if (this._made) return
145
146   var pattern = this.pattern
147   var options = this.options
148
149   // empty patterns and comments match nothing.
150   if (!options.nocomment && pattern.charAt(0) === '#') {
151     this.comment = true
152     return
153   }
154   if (!pattern) {
155     this.empty = true
156     return
157   }
158
159   // step 1: figure out negation, etc.
160   this.parseNegate()
161
162   // step 2: expand braces
163   var set = this.globSet = this.braceExpand()
164
165   if (options.debug) this.debug = console.error
166
167   this.debug(this.pattern, set)
168
169   // step 3: now we have a set, so turn each one into a series of path-portion
170   // matching patterns.
171   // These will be regexps, except in the case of "**", which is
172   // set to the GLOBSTAR object for globstar behavior,
173   // and will not contain any / characters
174   set = this.globParts = set.map(function (s) {
175     return s.split(slashSplit)
176   })
177
178   this.debug(this.pattern, set)
179
180   // glob --> regexps
181   set = set.map(function (s, si, set) {
182     return s.map(this.parse, this)
183   }, this)
184
185   this.debug(this.pattern, set)
186
187   // filter out everything that didn't compile properly.
188   set = set.filter(function (s) {
189     return s.indexOf(false) === -1
190   })
191
192   this.debug(this.pattern, set)
193
194   this.set = set
195 }
196
197 Minimatch.prototype.parseNegate = parseNegate
198 function parseNegate () {
199   var pattern = this.pattern
200   var negate = false
201   var options = this.options
202   var negateOffset = 0
203
204   if (options.nonegate) return
205
206   for (var i = 0, l = pattern.length
207     ; i < l && pattern.charAt(i) === '!'
208     ; i++) {
209     negate = !negate
210     negateOffset++
211   }
212
213   if (negateOffset) this.pattern = pattern.substr(negateOffset)
214   this.negate = negate
215 }
216
217 // Brace expansion:
218 // a{b,c}d -> abd acd
219 // a{b,}c -> abc ac
220 // a{0..3}d -> a0d a1d a2d a3d
221 // a{b,c{d,e}f}g -> abg acdfg acefg
222 // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
223 //
224 // Invalid sets are not expanded.
225 // a{2..}b -> a{2..}b
226 // a{b}c -> a{b}c
227 minimatch.braceExpand = function (pattern, options) {
228   return braceExpand(pattern, options)
229 }
230
231 Minimatch.prototype.braceExpand = braceExpand
232
233 function braceExpand (pattern, options) {
234   if (!options) {
235     if (this instanceof Minimatch) {
236       options = this.options
237     } else {
238       options = {}
239     }
240   }
241
242   pattern = typeof pattern === 'undefined'
243     ? this.pattern : pattern
244
245   if (typeof pattern === 'undefined') {
246     throw new TypeError('undefined pattern')
247   }
248
249   if (options.nobrace ||
250     !pattern.match(/\{.*\}/)) {
251     // shortcut. no need to expand.
252     return [pattern]
253   }
254
255   return expand(pattern)
256 }
257
258 // parse a component of the expanded set.
259 // At this point, no pattern may contain "/" in it
260 // so we're going to return a 2d array, where each entry is the full
261 // pattern, split on '/', and then turned into a regular expression.
262 // A regexp is made at the end which joins each array with an
263 // escaped /, and another full one which joins each regexp with |.
264 //
265 // Following the lead of Bash 4.1, note that "**" only has special meaning
266 // when it is the *only* thing in a path portion.  Otherwise, any series
267 // of * is equivalent to a single *.  Globstar behavior is enabled by
268 // default, and can be disabled by setting options.noglobstar.
269 Minimatch.prototype.parse = parse
270 var SUBPARSE = {}
271 function parse (pattern, isSub) {
272   if (pattern.length > 1024 * 64) {
273     throw new TypeError('pattern is too long')
274   }
275
276   var options = this.options
277
278   // shortcuts
279   if (!options.noglobstar && pattern === '**') return GLOBSTAR
280   if (pattern === '') return ''
281
282   var re = ''
283   var hasMagic = !!options.nocase
284   var escaping = false
285   // ? => one single character
286   var patternListStack = []
287   var negativeLists = []
288   var stateChar
289   var inClass = false
290   var reClassStart = -1
291   var classStart = -1
292   // . and .. never match anything that doesn't start with .,
293   // even when options.dot is set.
294   var patternStart = pattern.charAt(0) === '.' ? '' // anything
295   // not (start or / followed by . or .. followed by / or end)
296   : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
297   : '(?!\\.)'
298   var self = this
299
300   function clearStateChar () {
301     if (stateChar) {
302       // we had some state-tracking character
303       // that wasn't consumed by this pass.
304       switch (stateChar) {
305         case '*':
306           re += star
307           hasMagic = true
308         break
309         case '?':
310           re += qmark
311           hasMagic = true
312         break
313         default:
314           re += '\\' + stateChar
315         break
316       }
317       self.debug('clearStateChar %j %j', stateChar, re)
318       stateChar = false
319     }
320   }
321
322   for (var i = 0, len = pattern.length, c
323     ; (i < len) && (c = pattern.charAt(i))
324     ; i++) {
325     this.debug('%s\t%s %s %j', pattern, i, re, c)
326
327     // skip over any that are escaped.
328     if (escaping && reSpecials[c]) {
329       re += '\\' + c
330       escaping = false
331       continue
332     }
333
334     switch (c) {
335       case '/':
336         // completely not allowed, even escaped.
337         // Should already be path-split by now.
338         return false
339
340       case '\\':
341         clearStateChar()
342         escaping = true
343       continue
344
345       // the various stateChar values
346       // for the "extglob" stuff.
347       case '?':
348       case '*':
349       case '+':
350       case '@':
351       case '!':
352         this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
353
354         // all of those are literals inside a class, except that
355         // the glob [!a] means [^a] in regexp
356         if (inClass) {
357           this.debug('  in class')
358           if (c === '!' && i === classStart + 1) c = '^'
359           re += c
360           continue
361         }
362
363         // if we already have a stateChar, then it means
364         // that there was something like ** or +? in there.
365         // Handle the stateChar, then proceed with this one.
366         self.debug('call clearStateChar %j', stateChar)
367         clearStateChar()
368         stateChar = c
369         // if extglob is disabled, then +(asdf|foo) isn't a thing.
370         // just clear the statechar *now*, rather than even diving into
371         // the patternList stuff.
372         if (options.noext) clearStateChar()
373       continue
374
375       case '(':
376         if (inClass) {
377           re += '('
378           continue
379         }
380
381         if (!stateChar) {
382           re += '\\('
383           continue
384         }
385
386         patternListStack.push({
387           type: stateChar,
388           start: i - 1,
389           reStart: re.length,
390           open: plTypes[stateChar].open,
391           close: plTypes[stateChar].close
392         })
393         // negation is (?:(?!js)[^/]*)
394         re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
395         this.debug('plType %j %j', stateChar, re)
396         stateChar = false
397       continue
398
399       case ')':
400         if (inClass || !patternListStack.length) {
401           re += '\\)'
402           continue
403         }
404
405         clearStateChar()
406         hasMagic = true
407         var pl = patternListStack.pop()
408         // negation is (?:(?!js)[^/]*)
409         // The others are (?:<pattern>)<type>
410         re += pl.close
411         if (pl.type === '!') {
412           negativeLists.push(pl)
413         }
414         pl.reEnd = re.length
415       continue
416
417       case '|':
418         if (inClass || !patternListStack.length || escaping) {
419           re += '\\|'
420           escaping = false
421           continue
422         }
423
424         clearStateChar()
425         re += '|'
426       continue
427
428       // these are mostly the same in regexp and glob
429       case '[':
430         // swallow any state-tracking char before the [
431         clearStateChar()
432
433         if (inClass) {
434           re += '\\' + c
435           continue
436         }
437
438         inClass = true
439         classStart = i
440         reClassStart = re.length
441         re += c
442       continue
443
444       case ']':
445         //  a right bracket shall lose its special
446         //  meaning and represent itself in
447         //  a bracket expression if it occurs
448         //  first in the list.  -- POSIX.2 2.8.3.2
449         if (i === classStart + 1 || !inClass) {
450           re += '\\' + c
451           escaping = false
452           continue
453         }
454
455         // handle the case where we left a class open.
456         // "[z-a]" is valid, equivalent to "\[z-a\]"
457         if (inClass) {
458           // split where the last [ was, make sure we don't have
459           // an invalid re. if so, re-walk the contents of the
460           // would-be class to re-translate any characters that
461           // were passed through as-is
462           // TODO: It would probably be faster to determine this
463           // without a try/catch and a new RegExp, but it's tricky
464           // to do safely.  For now, this is safe and works.
465           var cs = pattern.substring(classStart + 1, i)
466           try {
467             RegExp('[' + cs + ']')
468           } catch (er) {
469             // not a valid class!
470             var sp = this.parse(cs, SUBPARSE)
471             re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
472             hasMagic = hasMagic || sp[1]
473             inClass = false
474             continue
475           }
476         }
477
478         // finish up the class.
479         hasMagic = true
480         inClass = false
481         re += c
482       continue
483
484       default:
485         // swallow any state char that wasn't consumed
486         clearStateChar()
487
488         if (escaping) {
489           // no need
490           escaping = false
491         } else if (reSpecials[c]
492           && !(c === '^' && inClass)) {
493           re += '\\'
494         }
495
496         re += c
497
498     } // switch
499   } // for
500
501   // handle the case where we left a class open.
502   // "[abc" is valid, equivalent to "\[abc"
503   if (inClass) {
504     // split where the last [ was, and escape it
505     // this is a huge pita.  We now have to re-walk
506     // the contents of the would-be class to re-translate
507     // any characters that were passed through as-is
508     cs = pattern.substr(classStart + 1)
509     sp = this.parse(cs, SUBPARSE)
510     re = re.substr(0, reClassStart) + '\\[' + sp[0]
511     hasMagic = hasMagic || sp[1]
512   }
513
514   // handle the case where we had a +( thing at the *end*
515   // of the pattern.
516   // each pattern list stack adds 3 chars, and we need to go through
517   // and escape any | chars that were passed through as-is for the regexp.
518   // Go through and escape them, taking care not to double-escape any
519   // | chars that were already escaped.
520   for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
521     var tail = re.slice(pl.reStart + pl.open.length)
522     this.debug('setting tail', re, pl)
523     // maybe some even number of \, then maybe 1 \, followed by a |
524     tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
525       if (!$2) {
526         // the | isn't already escaped, so escape it.
527         $2 = '\\'
528       }
529
530       // need to escape all those slashes *again*, without escaping the
531       // one that we need for escaping the | character.  As it works out,
532       // escaping an even number of slashes can be done by simply repeating
533       // it exactly after itself.  That's why this trick works.
534       //
535       // I am sorry that you have to see this.
536       return $1 + $1 + $2 + '|'
537     })
538
539     this.debug('tail=%j\n   %s', tail, tail, pl, re)
540     var t = pl.type === '*' ? star
541       : pl.type === '?' ? qmark
542       : '\\' + pl.type
543
544     hasMagic = true
545     re = re.slice(0, pl.reStart) + t + '\\(' + tail
546   }
547
548   // handle trailing things that only matter at the very end.
549   clearStateChar()
550   if (escaping) {
551     // trailing \\
552     re += '\\\\'
553   }
554
555   // only need to apply the nodot start if the re starts with
556   // something that could conceivably capture a dot
557   var addPatternStart = false
558   switch (re.charAt(0)) {
559     case '.':
560     case '[':
561     case '(': addPatternStart = true
562   }
563
564   // Hack to work around lack of negative lookbehind in JS
565   // A pattern like: *.!(x).!(y|z) needs to ensure that a name
566   // like 'a.xyz.yz' doesn't match.  So, the first negative
567   // lookahead, has to look ALL the way ahead, to the end of
568   // the pattern.
569   for (var n = negativeLists.length - 1; n > -1; n--) {
570     var nl = negativeLists[n]
571
572     var nlBefore = re.slice(0, nl.reStart)
573     var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
574     var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
575     var nlAfter = re.slice(nl.reEnd)
576
577     nlLast += nlAfter
578
579     // Handle nested stuff like *(*.js|!(*.json)), where open parens
580     // mean that we should *not* include the ) in the bit that is considered
581     // "after" the negated section.
582     var openParensBefore = nlBefore.split('(').length - 1
583     var cleanAfter = nlAfter
584     for (i = 0; i < openParensBefore; i++) {
585       cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
586     }
587     nlAfter = cleanAfter
588
589     var dollar = ''
590     if (nlAfter === '' && isSub !== SUBPARSE) {
591       dollar = '$'
592     }
593     var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
594     re = newRe
595   }
596
597   // if the re is not "" at this point, then we need to make sure
598   // it doesn't match against an empty path part.
599   // Otherwise a/* will match a/, which it should not.
600   if (re !== '' && hasMagic) {
601     re = '(?=.)' + re
602   }
603
604   if (addPatternStart) {
605     re = patternStart + re
606   }
607
608   // parsing just a piece of a larger pattern.
609   if (isSub === SUBPARSE) {
610     return [re, hasMagic]
611   }
612
613   // skip the regexp for non-magical patterns
614   // unescape anything in it, though, so that it'll be
615   // an exact match against a file etc.
616   if (!hasMagic) {
617     return globUnescape(pattern)
618   }
619
620   var flags = options.nocase ? 'i' : ''
621   try {
622     var regExp = new RegExp('^' + re + '$', flags)
623   } catch (er) {
624     // If it was an invalid regular expression, then it can't match
625     // anything.  This trick looks for a character after the end of
626     // the string, which is of course impossible, except in multi-line
627     // mode, but it's not a /m regex.
628     return new RegExp('$.')
629   }
630
631   regExp._glob = pattern
632   regExp._src = re
633
634   return regExp
635 }
636
637 minimatch.makeRe = function (pattern, options) {
638   return new Minimatch(pattern, options || {}).makeRe()
639 }
640
641 Minimatch.prototype.makeRe = makeRe
642 function makeRe () {
643   if (this.regexp || this.regexp === false) return this.regexp
644
645   // at this point, this.set is a 2d array of partial
646   // pattern strings, or "**".
647   //
648   // It's better to use .match().  This function shouldn't
649   // be used, really, but it's pretty convenient sometimes,
650   // when you just want to work with a regex.
651   var set = this.set
652
653   if (!set.length) {
654     this.regexp = false
655     return this.regexp
656   }
657   var options = this.options
658
659   var twoStar = options.noglobstar ? star
660     : options.dot ? twoStarDot
661     : twoStarNoDot
662   var flags = options.nocase ? 'i' : ''
663
664   var re = set.map(function (pattern) {
665     return pattern.map(function (p) {
666       return (p === GLOBSTAR) ? twoStar
667       : (typeof p === 'string') ? regExpEscape(p)
668       : p._src
669     }).join('\\\/')
670   }).join('|')
671
672   // must match entire pattern
673   // ending in a * or ** will make it less strict.
674   re = '^(?:' + re + ')$'
675
676   // can match anything, as long as it's not this.
677   if (this.negate) re = '^(?!' + re + ').*$'
678
679   try {
680     this.regexp = new RegExp(re, flags)
681   } catch (ex) {
682     this.regexp = false
683   }
684   return this.regexp
685 }
686
687 minimatch.match = function (list, pattern, options) {
688   options = options || {}
689   var mm = new Minimatch(pattern, options)
690   list = list.filter(function (f) {
691     return mm.match(f)
692   })
693   if (mm.options.nonull && !list.length) {
694     list.push(pattern)
695   }
696   return list
697 }
698
699 Minimatch.prototype.match = match
700 function match (f, partial) {
701   this.debug('match', f, this.pattern)
702   // short-circuit in the case of busted things.
703   // comments, etc.
704   if (this.comment) return false
705   if (this.empty) return f === ''
706
707   if (f === '/' && partial) return true
708
709   var options = this.options
710
711   // windows: need to use /, not \
712   if (path.sep !== '/') {
713     f = f.split(path.sep).join('/')
714   }
715
716   // treat the test path as a set of pathparts.
717   f = f.split(slashSplit)
718   this.debug(this.pattern, 'split', f)
719
720   // just ONE of the pattern sets in this.set needs to match
721   // in order for it to be valid.  If negating, then just one
722   // match means that we have failed.
723   // Either way, return on the first hit.
724
725   var set = this.set
726   this.debug(this.pattern, 'set', set)
727
728   // Find the basename of the path by looking for the last non-empty segment
729   var filename
730   var i
731   for (i = f.length - 1; i >= 0; i--) {
732     filename = f[i]
733     if (filename) break
734   }
735
736   for (i = 0; i < set.length; i++) {
737     var pattern = set[i]
738     var file = f
739     if (options.matchBase && pattern.length === 1) {
740       file = [filename]
741     }
742     var hit = this.matchOne(file, pattern, partial)
743     if (hit) {
744       if (options.flipNegate) return true
745       return !this.negate
746     }
747   }
748
749   // didn't get any hits.  this is success if it's a negative
750   // pattern, failure otherwise.
751   if (options.flipNegate) return false
752   return this.negate
753 }
754
755 // set partial to true to test if, for example,
756 // "/a/b" matches the start of "/*/b/*/d"
757 // Partial means, if you run out of file before you run
758 // out of pattern, then that's fine, as long as all
759 // the parts match.
760 Minimatch.prototype.matchOne = function (file, pattern, partial) {
761   var options = this.options
762
763   this.debug('matchOne',
764     { 'this': this, file: file, pattern: pattern })
765
766   this.debug('matchOne', file.length, pattern.length)
767
768   for (var fi = 0,
769       pi = 0,
770       fl = file.length,
771       pl = pattern.length
772       ; (fi < fl) && (pi < pl)
773       ; fi++, pi++) {
774     this.debug('matchOne loop')
775     var p = pattern[pi]
776     var f = file[fi]
777
778     this.debug(pattern, p, f)
779
780     // should be impossible.
781     // some invalid regexp stuff in the set.
782     if (p === false) return false
783
784     if (p === GLOBSTAR) {
785       this.debug('GLOBSTAR', [pattern, p, f])
786
787       // "**"
788       // a/**/b/**/c would match the following:
789       // a/b/x/y/z/c
790       // a/x/y/z/b/c
791       // a/b/x/b/x/c
792       // a/b/c
793       // To do this, take the rest of the pattern after
794       // the **, and see if it would match the file remainder.
795       // If so, return success.
796       // If not, the ** "swallows" a segment, and try again.
797       // This is recursively awful.
798       //
799       // a/**/b/**/c matching a/b/x/y/z/c
800       // - a matches a
801       // - doublestar
802       //   - matchOne(b/x/y/z/c, b/**/c)
803       //     - b matches b
804       //     - doublestar
805       //       - matchOne(x/y/z/c, c) -> no
806       //       - matchOne(y/z/c, c) -> no
807       //       - matchOne(z/c, c) -> no
808       //       - matchOne(c, c) yes, hit
809       var fr = fi
810       var pr = pi + 1
811       if (pr === pl) {
812         this.debug('** at the end')
813         // a ** at the end will just swallow the rest.
814         // We have found a match.
815         // however, it will not swallow /.x, unless
816         // options.dot is set.
817         // . and .. are *never* matched by **, for explosively
818         // exponential reasons.
819         for (; fi < fl; fi++) {
820           if (file[fi] === '.' || file[fi] === '..' ||
821             (!options.dot && file[fi].charAt(0) === '.')) return false
822         }
823         return true
824       }
825
826       // ok, let's see if we can swallow whatever we can.
827       while (fr < fl) {
828         var swallowee = file[fr]
829
830         this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
831
832         // XXX remove this slice.  Just pass the start index.
833         if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
834           this.debug('globstar found match!', fr, fl, swallowee)
835           // found a match.
836           return true
837         } else {
838           // can't swallow "." or ".." ever.
839           // can only swallow ".foo" when explicitly asked.
840           if (swallowee === '.' || swallowee === '..' ||
841             (!options.dot && swallowee.charAt(0) === '.')) {
842             this.debug('dot detected!', file, fr, pattern, pr)
843             break
844           }
845
846           // ** swallows a segment, and continue.
847           this.debug('globstar swallow a segment, and continue')
848           fr++
849         }
850       }
851
852       // no match was found.
853       // However, in partial mode, we can't say this is necessarily over.
854       // If there's more *pattern* left, then
855       if (partial) {
856         // ran out of file
857         this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
858         if (fr === fl) return true
859       }
860       return false
861     }
862
863     // something other than **
864     // non-magic patterns just have to match exactly
865     // patterns with magic have been turned into regexps.
866     var hit
867     if (typeof p === 'string') {
868       if (options.nocase) {
869         hit = f.toLowerCase() === p.toLowerCase()
870       } else {
871         hit = f === p
872       }
873       this.debug('string match', p, f, hit)
874     } else {
875       hit = f.match(p)
876       this.debug('pattern match', p, f, hit)
877     }
878
879     if (!hit) return false
880   }
881
882   // Note: ending in / means that we'll get a final ""
883   // at the end of the pattern.  This can only match a
884   // corresponding "" at the end of the file.
885   // If the file ends in /, then it can only match a
886   // a pattern that ends in /, unless the pattern just
887   // doesn't have any more for it. But, a/b/ should *not*
888   // match "a/b/*", even though "" matches against the
889   // [^/]*? pattern, except in partial mode, where it might
890   // simply not be reached yet.
891   // However, a/b/ should still satisfy a/*
892
893   // now either we fell off the end of the pattern, or we're done.
894   if (fi === fl && pi === pl) {
895     // ran out of pattern and filename at the same time.
896     // an exact hit!
897     return true
898   } else if (fi === fl) {
899     // ran out of file, but still had pattern left.
900     // this is ok if we're doing the match as part of
901     // a glob fs traversal.
902     return partial
903   } else if (pi === pl) {
904     // ran out of pattern, still have file left.
905     // this is only acceptable if we're on the very last
906     // empty segment of a file with a trailing slash.
907     // a/* should match a/b/
908     var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
909     return emptyFileEnd
910   }
911
912   // should be unreachable.
913   throw new Error('wtf?')
914 }
915
916 // replace stuff like \* with *
917 function globUnescape (s) {
918   return s.replace(/\\(.)/g, '$1')
919 }
920
921 function regExpEscape (s) {
922   return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
923 }