diff --git a/package-lock.json b/package-lock.json index ddf8cea0..37579272 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "minimatch", - "version": "6.0.2", + "version": "6.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "minimatch", - "version": "6.0.2", + "version": "6.0.3", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" diff --git a/package.json b/package.json index 0e8645d1..4948c1bf 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Isaac Z. Schlueter (http://blog.izs.me)", "name": "minimatch", "description": "a glob matcher in javascript", - "version": "6.0.2", + "version": "6.0.3", "repository": { "type": "git", "url": "git://github.com/isaacs/minimatch.git" diff --git a/src/index.ts b/src/index.ts index 85826622..f9d822f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -309,12 +309,24 @@ export class Minimatch { // These will be regexps, except in the case of "**", which is // set to the GLOBSTAR object for globstar behavior, // and will not contain any / characters - const globParts = (this.globParts = globSet.map(s => s.split(slashSplit))) + const rawGlobParts = globSet.map(s => s.split(slashSplit)) + + // consecutive globstars are an unncessary perf killer + this.globParts = this.options.noglobstar + ? rawGlobParts + : rawGlobParts.map(parts => + parts.reduce((set: string[], part) => { + if (part !== '**' || set[set.length - 1] !== '**') { + set.push(part) + } + return set + }, []) + ) - this.debug(this.pattern, globParts) + this.debug(this.pattern, this.globParts) // glob --> regexps - let set = globParts.map((s, _, __) => s.map(ss => this.parse(ss))) + let set = this.globParts.map((s, _, __) => s.map(ss => this.parse(ss))) this.debug(this.pattern, set) @@ -921,32 +933,21 @@ export class Minimatch { : twoStarNoDot const flags = options.nocase ? 'i' : '' - // coalesce globstars and regexpify non-globstar patterns - // if it's the only item, then we just do one twoStar - // if it's the first, and there are more, prepend (\/|twoStar\/)? to next - // if it's the last, append (\/twoStar|) to previous - // if it's in the middle, append (\/|\/twoStar\/) to previous + // regexpify non-globstar patterns + // if ** is only item, then we just do one twoStar + // if ** is first, and there are more, prepend (\/|twoStar\/)? to next + // if ** is last, append (\/twoStar|) to previous + // if ** is in the middle, append (\/|\/twoStar\/) to previous // then filter out GLOBSTAR symbols let re = set .map(pattern => { - const pp: (string | typeof GLOBSTAR)[] = pattern - .map(p => - typeof p === 'string' - ? regExpEscape(p) - : p === GLOBSTAR - ? GLOBSTAR - : p._src - ) - .reduce((set: (string | typeof GLOBSTAR)[], p) => { - if ( - (set[set.length - 1] === GLOBSTAR && p === GLOBSTAR) || - p === undefined - ) { - return set - } - set.push(p) - return set - }, []) + const pp: (string | typeof GLOBSTAR)[] = pattern.map(p => + typeof p === 'string' + ? regExpEscape(p) + : p === GLOBSTAR + ? GLOBSTAR + : p._src + ) as (string | typeof GLOBSTAR)[] pp.forEach((p, i) => { const next = pp[i + 1] const prev = pp[i - 1] diff --git a/test/consecutive-glob-stars.js b/test/consecutive-glob-stars.js new file mode 100644 index 00000000..cd5555aa --- /dev/null +++ b/test/consecutive-glob-stars.js @@ -0,0 +1,15 @@ +const t = require('tap') +const {Minimatch, GLOBSTAR} = require('../') + +const patterns = [] +for (const a of ['**', '**/**', '**/**/**']) { + for (const b of['**', '**/**', '**/**/**']) { + for (const c of ['**', '**/**', '**/**/**']) { + patterns.push(`x/${a}/y/${b}/z/${c}`) + } + } +} + +for (const m of patterns.map(p => new Minimatch(p))) { + t.same(m.globParts, [['x', '**', 'y', '**', 'z', '**']]) +}