1 module.exports = minimatch
2 minimatch.Minimatch = Minimatch
4 var path = { sep: '/' }
9 var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
10 var expand = require('brace-expansion')
13 '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
14 '?': { open: '(?:', close: ')?' },
15 '+': { open: '(?:', close: ')+' },
16 '*': { open: '(?:', close: ')*' },
17 '@': { open: '(?:', close: ')' }
20 // any single thing other than /
21 // don't need to escape / when using new RegExp()
24 // * => any number of characters
25 var star = qmark + '*?'
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})($|\\\/)).)*?'
32 // not a ^ or / followed by a dot,
33 // followed by anything, any number of times.
34 var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
36 // characters that need to be escaped in RegExp.
37 var reSpecials = charSet('().*{}+?[]^$\\!')
39 // "abc" -> { a:true, b:true, c:true }
40 function charSet (s) {
41 return s.split('').reduce(function (set, c) {
47 // normalizes slashes.
48 var slashSplit = /\/+/
50 minimatch.filter = filter
51 function filter (pattern, options) {
52 options = options || {}
53 return function (p, i, list) {
54 return minimatch(p, pattern, options)
62 Object.keys(b).forEach(function (k) {
65 Object.keys(a).forEach(function (k) {
71 minimatch.defaults = function (def) {
72 if (!def || !Object.keys(def).length) return minimatch
76 var m = function minimatch (p, pattern, options) {
77 return orig.minimatch(p, pattern, ext(def, options))
80 m.Minimatch = function Minimatch (pattern, options) {
81 return new orig.Minimatch(pattern, ext(def, options))
87 Minimatch.defaults = function (def) {
88 if (!def || !Object.keys(def).length) return Minimatch
89 return minimatch.defaults(def).Minimatch
92 function minimatch (p, pattern, options) {
93 if (typeof pattern !== 'string') {
94 throw new TypeError('glob pattern string required')
97 if (!options) options = {}
99 // shortcut: comments match nothing.
100 if (!options.nocomment && pattern.charAt(0) === '#') {
104 // "" only matches ""
105 if (pattern.trim() === '') return p === ''
107 return new Minimatch(pattern, options).match(p)
110 function Minimatch (pattern, options) {
111 if (!(this instanceof Minimatch)) {
112 return new Minimatch(pattern, options)
115 if (typeof pattern !== 'string') {
116 throw new TypeError('glob pattern string required')
119 if (!options) options = {}
120 pattern = pattern.trim()
122 // windows support: need to use /, not \
123 if (path.sep !== '/') {
124 pattern = pattern.split(path.sep).join('/')
127 this.options = options
129 this.pattern = pattern
135 // make the set of regexps etc.
139 Minimatch.prototype.debug = function () {}
141 Minimatch.prototype.make = make
143 // don't do it more than once.
144 if (this._made) return
146 var pattern = this.pattern
147 var options = this.options
149 // empty patterns and comments match nothing.
150 if (!options.nocomment && pattern.charAt(0) === '#') {
159 // step 1: figure out negation, etc.
162 // step 2: expand braces
163 var set = this.globSet = this.braceExpand()
165 if (options.debug) this.debug = console.error
167 this.debug(this.pattern, set)
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)
178 this.debug(this.pattern, set)
181 set = set.map(function (s, si, set) {
182 return s.map(this.parse, this)
185 this.debug(this.pattern, set)
187 // filter out everything that didn't compile properly.
188 set = set.filter(function (s) {
189 return s.indexOf(false) === -1
192 this.debug(this.pattern, set)
197 Minimatch.prototype.parseNegate = parseNegate
198 function parseNegate () {
199 var pattern = this.pattern
201 var options = this.options
204 if (options.nonegate) return
206 for (var i = 0, l = pattern.length
207 ; i < l && pattern.charAt(i) === '!'
213 if (negateOffset) this.pattern = pattern.substr(negateOffset)
218 // a{b,c}d -> abd acd
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
224 // Invalid sets are not expanded.
225 // a{2..}b -> a{2..}b
227 minimatch.braceExpand = function (pattern, options) {
228 return braceExpand(pattern, options)
231 Minimatch.prototype.braceExpand = braceExpand
233 function braceExpand (pattern, options) {
235 if (this instanceof Minimatch) {
236 options = this.options
242 pattern = typeof pattern === 'undefined'
243 ? this.pattern : pattern
245 if (typeof pattern === 'undefined') {
246 throw new TypeError('undefined pattern')
249 if (options.nobrace ||
250 !pattern.match(/\{.*\}/)) {
251 // shortcut. no need to expand.
255 return expand(pattern)
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 |.
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
271 function parse (pattern, isSub) {
272 if (pattern.length > 1024 * 64) {
273 throw new TypeError('pattern is too long')
276 var options = this.options
279 if (!options.noglobstar && pattern === '**') return GLOBSTAR
280 if (pattern === '') return ''
283 var hasMagic = !!options.nocase
285 // ? => one single character
286 var patternListStack = []
287 var negativeLists = []
290 var reClassStart = -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}(?:$|\\\/))'
300 function clearStateChar () {
302 // we had some state-tracking character
303 // that wasn't consumed by this pass.
314 re += '\\' + stateChar
317 self.debug('clearStateChar %j %j', stateChar, re)
322 for (var i = 0, len = pattern.length, c
323 ; (i < len) && (c = pattern.charAt(i))
325 this.debug('%s\t%s %s %j', pattern, i, re, c)
327 // skip over any that are escaped.
328 if (escaping && reSpecials[c]) {
336 // completely not allowed, even escaped.
337 // Should already be path-split by now.
345 // the various stateChar values
346 // for the "extglob" stuff.
352 this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
354 // all of those are literals inside a class, except that
355 // the glob [!a] means [^a] in regexp
357 this.debug(' in class')
358 if (c === '!' && i === classStart + 1) c = '^'
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)
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()
386 patternListStack.push({
390 open: plTypes[stateChar].open,
391 close: plTypes[stateChar].close
393 // negation is (?:(?!js)[^/]*)
394 re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
395 this.debug('plType %j %j', stateChar, re)
400 if (inClass || !patternListStack.length) {
407 var pl = patternListStack.pop()
408 // negation is (?:(?!js)[^/]*)
409 // The others are (?:<pattern>)<type>
411 if (pl.type === '!') {
412 negativeLists.push(pl)
418 if (inClass || !patternListStack.length || escaping) {
428 // these are mostly the same in regexp and glob
430 // swallow any state-tracking char before the [
440 reClassStart = re.length
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) {
455 // handle the case where we left a class open.
456 // "[z-a]" is valid, equivalent to "\[z-a\]"
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)
467 RegExp('[' + cs + ']')
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]
478 // finish up the class.
485 // swallow any state char that wasn't consumed
491 } else if (reSpecials[c]
492 && !(c === '^' && inClass)) {
501 // handle the case where we left a class open.
502 // "[abc" is valid, equivalent to "\[abc"
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]
514 // handle the case where we had a +( thing at the *end*
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) {
526 // the | isn't already escaped, so escape it.
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.
535 // I am sorry that you have to see this.
536 return $1 + $1 + $2 + '|'
539 this.debug('tail=%j\n %s', tail, tail, pl, re)
540 var t = pl.type === '*' ? star
541 : pl.type === '?' ? qmark
545 re = re.slice(0, pl.reStart) + t + '\\(' + tail
548 // handle trailing things that only matter at the very end.
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)) {
561 case '(': addPatternStart = true
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
569 for (var n = negativeLists.length - 1; n > -1; n--) {
570 var nl = negativeLists[n]
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)
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(/\)[+*?]?/, '')
590 if (nlAfter === '' && isSub !== SUBPARSE) {
593 var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
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) {
604 if (addPatternStart) {
605 re = patternStart + re
608 // parsing just a piece of a larger pattern.
609 if (isSub === SUBPARSE) {
610 return [re, hasMagic]
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.
617 return globUnescape(pattern)
620 var flags = options.nocase ? 'i' : ''
622 var regExp = new RegExp('^' + re + '$', flags)
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('$.')
631 regExp._glob = pattern
637 minimatch.makeRe = function (pattern, options) {
638 return new Minimatch(pattern, options || {}).makeRe()
641 Minimatch.prototype.makeRe = makeRe
643 if (this.regexp || this.regexp === false) return this.regexp
645 // at this point, this.set is a 2d array of partial
646 // pattern strings, or "**".
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.
657 var options = this.options
659 var twoStar = options.noglobstar ? star
660 : options.dot ? twoStarDot
662 var flags = options.nocase ? 'i' : ''
664 var re = set.map(function (pattern) {
665 return pattern.map(function (p) {
666 return (p === GLOBSTAR) ? twoStar
667 : (typeof p === 'string') ? regExpEscape(p)
672 // must match entire pattern
673 // ending in a * or ** will make it less strict.
674 re = '^(?:' + re + ')$'
676 // can match anything, as long as it's not this.
677 if (this.negate) re = '^(?!' + re + ').*$'
680 this.regexp = new RegExp(re, flags)
687 minimatch.match = function (list, pattern, options) {
688 options = options || {}
689 var mm = new Minimatch(pattern, options)
690 list = list.filter(function (f) {
693 if (mm.options.nonull && !list.length) {
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.
704 if (this.comment) return false
705 if (this.empty) return f === ''
707 if (f === '/' && partial) return true
709 var options = this.options
711 // windows: need to use /, not \
712 if (path.sep !== '/') {
713 f = f.split(path.sep).join('/')
716 // treat the test path as a set of pathparts.
717 f = f.split(slashSplit)
718 this.debug(this.pattern, 'split', f)
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.
726 this.debug(this.pattern, 'set', set)
728 // Find the basename of the path by looking for the last non-empty segment
731 for (i = f.length - 1; i >= 0; i--) {
736 for (i = 0; i < set.length; i++) {
739 if (options.matchBase && pattern.length === 1) {
742 var hit = this.matchOne(file, pattern, partial)
744 if (options.flipNegate) return true
749 // didn't get any hits. this is success if it's a negative
750 // pattern, failure otherwise.
751 if (options.flipNegate) return false
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
760 Minimatch.prototype.matchOne = function (file, pattern, partial) {
761 var options = this.options
763 this.debug('matchOne',
764 { 'this': this, file: file, pattern: pattern })
766 this.debug('matchOne', file.length, pattern.length)
772 ; (fi < fl) && (pi < pl)
774 this.debug('matchOne loop')
778 this.debug(pattern, p, f)
780 // should be impossible.
781 // some invalid regexp stuff in the set.
782 if (p === false) return false
784 if (p === GLOBSTAR) {
785 this.debug('GLOBSTAR', [pattern, p, f])
788 // a/**/b/**/c would match the following:
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.
799 // a/**/b/**/c matching a/b/x/y/z/c
802 // - matchOne(b/x/y/z/c, b/**/c)
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
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
826 // ok, let's see if we can swallow whatever we can.
828 var swallowee = file[fr]
830 this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
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)
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)
846 // ** swallows a segment, and continue.
847 this.debug('globstar swallow a segment, and continue')
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
857 this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
858 if (fr === fl) return true
863 // something other than **
864 // non-magic patterns just have to match exactly
865 // patterns with magic have been turned into regexps.
867 if (typeof p === 'string') {
868 if (options.nocase) {
869 hit = f.toLowerCase() === p.toLowerCase()
873 this.debug('string match', p, f, hit)
876 this.debug('pattern match', p, f, hit)
879 if (!hit) return false
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/*
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.
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.
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] === '')
912 // should be unreachable.
913 throw new Error('wtf?')
916 // replace stuff like \* with *
917 function globUnescape (s) {
918 return s.replace(/\\(.)/g, '$1')
921 function regExpEscape (s) {
922 return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')