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