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