minimatch.js 26 KB

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