summaryrefslogtreecommitdiff
path: root/node_modules/minimatch/dist/mjs/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/minimatch/dist/mjs/index.js')
-rw-r--r--node_modules/minimatch/dist/mjs/index.js995
1 files changed, 995 insertions, 0 deletions
diff --git a/node_modules/minimatch/dist/mjs/index.js b/node_modules/minimatch/dist/mjs/index.js
new file mode 100644
index 0000000..831b6a6
--- /dev/null
+++ b/node_modules/minimatch/dist/mjs/index.js
@@ -0,0 +1,995 @@
+import expand from 'brace-expansion';
+import { assertValidPattern } from './assert-valid-pattern.js';
+import { AST } from './ast.js';
+import { escape } from './escape.js';
+import { unescape } from './unescape.js';
+export const minimatch = (p, pattern, options = {}) => {
+ assertValidPattern(pattern);
+ // shortcut: comments match nothing.
+ if (!options.nocomment && pattern.charAt(0) === '#') {
+ return false;
+ }
+ return new Minimatch(pattern, options).match(p);
+};
+// Optimized checking for the most common glob patterns.
+const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
+const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
+const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
+const starDotExtTestNocase = (ext) => {
+ ext = ext.toLowerCase();
+ return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
+};
+const starDotExtTestNocaseDot = (ext) => {
+ ext = ext.toLowerCase();
+ return (f) => f.toLowerCase().endsWith(ext);
+};
+const starDotStarRE = /^\*+\.\*+$/;
+const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
+const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
+const dotStarRE = /^\.\*+$/;
+const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
+const starRE = /^\*+$/;
+const starTest = (f) => f.length !== 0 && !f.startsWith('.');
+const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
+const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
+const qmarksTestNocase = ([$0, ext = '']) => {
+ const noext = qmarksTestNoExt([$0]);
+ if (!ext)
+ return noext;
+ ext = ext.toLowerCase();
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext);
+};
+const qmarksTestNocaseDot = ([$0, ext = '']) => {
+ const noext = qmarksTestNoExtDot([$0]);
+ if (!ext)
+ return noext;
+ ext = ext.toLowerCase();
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext);
+};
+const qmarksTestDot = ([$0, ext = '']) => {
+ const noext = qmarksTestNoExtDot([$0]);
+ return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
+};
+const qmarksTest = ([$0, ext = '']) => {
+ const noext = qmarksTestNoExt([$0]);
+ return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
+};
+const qmarksTestNoExt = ([$0]) => {
+ const len = $0.length;
+ return (f) => f.length === len && !f.startsWith('.');
+};
+const qmarksTestNoExtDot = ([$0]) => {
+ const len = $0.length;
+ return (f) => f.length === len && f !== '.' && f !== '..';
+};
+/* c8 ignore start */
+const defaultPlatform = (typeof process === 'object' && process
+ ? (typeof process.env === 'object' &&
+ process.env &&
+ process.env.__MINIMATCH_TESTING_PLATFORM__) ||
+ process.platform
+ : 'posix');
+const path = {
+ win32: { sep: '\\' },
+ posix: { sep: '/' },
+};
+/* c8 ignore stop */
+export const sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep;
+minimatch.sep = sep;
+export const GLOBSTAR = Symbol('globstar **');
+minimatch.GLOBSTAR = GLOBSTAR;
+// any single thing other than /
+// don't need to escape / when using new RegExp()
+const qmark = '[^/]';
+// * => any number of characters
+const star = qmark + '*?';
+// ** when dots are allowed. Anything goes, except .. and .
+// not (^ or / followed by one or two dots followed by $ or /),
+// followed by anything, any number of times.
+const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
+// not a ^ or / followed by a dot,
+// followed by anything, any number of times.
+const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
+export const filter = (pattern, options = {}) => (p) => minimatch(p, pattern, options);
+minimatch.filter = filter;
+const ext = (a, b = {}) => Object.assign({}, a, b);
+export const defaults = (def) => {
+ if (!def || typeof def !== 'object' || !Object.keys(def).length) {
+ return minimatch;
+ }
+ const orig = minimatch;
+ const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
+ return Object.assign(m, {
+ Minimatch: class Minimatch extends orig.Minimatch {
+ constructor(pattern, options = {}) {
+ super(pattern, ext(def, options));
+ }
+ static defaults(options) {
+ return orig.defaults(ext(def, options)).Minimatch;
+ }
+ },
+ AST: class AST extends orig.AST {
+ /* c8 ignore start */
+ constructor(type, parent, options = {}) {
+ super(type, parent, ext(def, options));
+ }
+ /* c8 ignore stop */
+ static fromGlob(pattern, options = {}) {
+ return orig.AST.fromGlob(pattern, ext(def, options));
+ }
+ },
+ unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
+ escape: (s, options = {}) => orig.escape(s, ext(def, options)),
+ filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
+ defaults: (options) => orig.defaults(ext(def, options)),
+ makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
+ braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
+ match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
+ sep: orig.sep,
+ GLOBSTAR: GLOBSTAR,
+ });
+};
+minimatch.defaults = defaults;
+// Brace expansion:
+// a{b,c}d -> abd acd
+// a{b,}c -> abc ac
+// a{0..3}d -> a0d a1d a2d a3d
+// a{b,c{d,e}f}g -> abg acdfg acefg
+// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
+//
+// Invalid sets are not expanded.
+// a{2..}b -> a{2..}b
+// a{b}c -> a{b}c
+export const braceExpand = (pattern, options = {}) => {
+ assertValidPattern(pattern);
+ // Thanks to Yeting Li <https://github.com/yetingli> for
+ // improving this regexp to avoid a ReDOS vulnerability.
+ if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
+ // shortcut. no need to expand.
+ return [pattern];
+ }
+ return expand(pattern);
+};
+minimatch.braceExpand = braceExpand;
+// parse a component of the expanded set.
+// At this point, no pattern may contain "/" in it
+// so we're going to return a 2d array, where each entry is the full
+// pattern, split on '/', and then turned into a regular expression.
+// A regexp is made at the end which joins each array with an
+// escaped /, and another full one which joins each regexp with |.
+//
+// Following the lead of Bash 4.1, note that "**" only has special meaning
+// when it is the *only* thing in a path portion. Otherwise, any series
+// of * is equivalent to a single *. Globstar behavior is enabled by
+// default, and can be disabled by setting options.noglobstar.
+export const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
+minimatch.makeRe = makeRe;
+export const match = (list, pattern, options = {}) => {
+ const mm = new Minimatch(pattern, options);
+ list = list.filter(f => mm.match(f));
+ if (mm.options.nonull && !list.length) {
+ list.push(pattern);
+ }
+ return list;
+};
+minimatch.match = match;
+// replace stuff like \* with *
+const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
+const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+export class Minimatch {
+ options;
+ set;
+ pattern;
+ windowsPathsNoEscape;
+ nonegate;
+ negate;
+ comment;
+ empty;
+ preserveMultipleSlashes;
+ partial;
+ globSet;
+ globParts;
+ nocase;
+ isWindows;
+ platform;
+ windowsNoMagicRoot;
+ regexp;
+ constructor(pattern, options = {}) {
+ assertValidPattern(pattern);
+ options = options || {};
+ this.options = options;
+ this.pattern = pattern;
+ this.platform = options.platform || defaultPlatform;
+ this.isWindows = this.platform === 'win32';
+ this.windowsPathsNoEscape =
+ !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
+ if (this.windowsPathsNoEscape) {
+ this.pattern = this.pattern.replace(/\\/g, '/');
+ }
+ this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
+ this.regexp = null;
+ this.negate = false;
+ this.nonegate = !!options.nonegate;
+ this.comment = false;
+ this.empty = false;
+ this.partial = !!options.partial;
+ this.nocase = !!this.options.nocase;
+ this.windowsNoMagicRoot =
+ options.windowsNoMagicRoot !== undefined
+ ? options.windowsNoMagicRoot
+ : !!(this.isWindows && this.nocase);
+ this.globSet = [];
+ this.globParts = [];
+ this.set = [];
+ // make the set of regexps etc.
+ this.make();
+ }
+ hasMagic() {
+ if (this.options.magicalBraces && this.set.length > 1) {
+ return true;
+ }
+ for (const pattern of this.set) {
+ for (const part of pattern) {
+ if (typeof part !== 'string')
+ return true;
+ }
+ }
+ return false;
+ }
+ debug(..._) { }
+ make() {
+ const pattern = this.pattern;
+ const options = this.options;
+ // empty patterns and comments match nothing.
+ if (!options.nocomment && pattern.charAt(0) === '#') {
+ this.comment = true;
+ return;
+ }
+ if (!pattern) {
+ this.empty = true;
+ return;
+ }
+ // step 1: figure out negation, etc.
+ this.parseNegate();
+ // step 2: expand braces
+ this.globSet = [...new Set(this.braceExpand())];
+ if (options.debug) {
+ this.debug = (...args) => console.error(...args);
+ }
+ this.debug(this.pattern, this.globSet);
+ // step 3: now we have a set, so turn each one into a series of
+ // path-portion matching patterns.
+ // 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
+ //
+ // First, we preprocess to make the glob pattern sets a bit simpler
+ // and deduped. There are some perf-killing patterns that can cause
+ // problems with a glob walk, but we can simplify them down a bit.
+ const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
+ this.globParts = this.preprocess(rawGlobParts);
+ this.debug(this.pattern, this.globParts);
+ // glob --> regexps
+ let set = this.globParts.map((s, _, __) => {
+ if (this.isWindows && this.windowsNoMagicRoot) {
+ // check if it's a drive or unc path.
+ const isUNC = s[0] === '' &&
+ s[1] === '' &&
+ (s[2] === '?' || !globMagic.test(s[2])) &&
+ !globMagic.test(s[3]);
+ const isDrive = /^[a-z]:/i.test(s[0]);
+ if (isUNC) {
+ return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))];
+ }
+ else if (isDrive) {
+ return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
+ }
+ }
+ return s.map(ss => this.parse(ss));
+ });
+ this.debug(this.pattern, set);
+ // filter out everything that didn't compile properly.
+ this.set = set.filter(s => s.indexOf(false) === -1);
+ // do not treat the ? in UNC paths as magic
+ if (this.isWindows) {
+ for (let i = 0; i < this.set.length; i++) {
+ const p = this.set[i];
+ if (p[0] === '' &&
+ p[1] === '' &&
+ this.globParts[i][2] === '?' &&
+ typeof p[3] === 'string' &&
+ /^[a-z]:$/i.test(p[3])) {
+ p[2] = '?';
+ }
+ }
+ }
+ this.debug(this.pattern, this.set);
+ }
+ // various transforms to equivalent pattern sets that are
+ // faster to process in a filesystem walk. The goal is to
+ // eliminate what we can, and push all ** patterns as far
+ // to the right as possible, even if it increases the number
+ // of patterns that we have to process.
+ preprocess(globParts) {
+ // if we're not in globstar mode, then turn all ** into *
+ if (this.options.noglobstar) {
+ for (let i = 0; i < globParts.length; i++) {
+ for (let j = 0; j < globParts[i].length; j++) {
+ if (globParts[i][j] === '**') {
+ globParts[i][j] = '*';
+ }
+ }
+ }
+ }
+ const { optimizationLevel = 1 } = this.options;
+ if (optimizationLevel >= 2) {
+ // aggressive optimization for the purpose of fs walking
+ globParts = this.firstPhasePreProcess(globParts);
+ globParts = this.secondPhasePreProcess(globParts);
+ }
+ else if (optimizationLevel >= 1) {
+ // just basic optimizations to remove some .. parts
+ globParts = this.levelOneOptimize(globParts);
+ }
+ else {
+ globParts = this.adjascentGlobstarOptimize(globParts);
+ }
+ return globParts;
+ }
+ // just get rid of adjascent ** portions
+ adjascentGlobstarOptimize(globParts) {
+ return globParts.map(parts => {
+ let gs = -1;
+ while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
+ let i = gs;
+ while (parts[i + 1] === '**') {
+ i++;
+ }
+ if (i !== gs) {
+ parts.splice(gs, i - gs);
+ }
+ }
+ return parts;
+ });
+ }
+ // get rid of adjascent ** and resolve .. portions
+ levelOneOptimize(globParts) {
+ return globParts.map(parts => {
+ parts = parts.reduce((set, part) => {
+ const prev = set[set.length - 1];
+ if (part === '**' && prev === '**') {
+ return set;
+ }
+ if (part === '..') {
+ if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
+ set.pop();
+ return set;
+ }
+ }
+ set.push(part);
+ return set;
+ }, []);
+ return parts.length === 0 ? [''] : parts;
+ });
+ }
+ levelTwoFileOptimize(parts) {
+ if (!Array.isArray(parts)) {
+ parts = this.slashSplit(parts);
+ }
+ let didSomething = false;
+ do {
+ didSomething = false;
+ // <pre>/<e>/<rest> -> <pre>/<rest>
+ if (!this.preserveMultipleSlashes) {
+ for (let i = 1; i < parts.length - 1; i++) {
+ const p = parts[i];
+ // don't squeeze out UNC patterns
+ if (i === 1 && p === '' && parts[0] === '')
+ continue;
+ if (p === '.' || p === '') {
+ didSomething = true;
+ parts.splice(i, 1);
+ i--;
+ }
+ }
+ if (parts[0] === '.' &&
+ parts.length === 2 &&
+ (parts[1] === '.' || parts[1] === '')) {
+ didSomething = true;
+ parts.pop();
+ }
+ }
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
+ let dd = 0;
+ while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
+ const p = parts[dd - 1];
+ if (p && p !== '.' && p !== '..' && p !== '**') {
+ didSomething = true;
+ parts.splice(dd - 1, 2);
+ dd -= 2;
+ }
+ }
+ } while (didSomething);
+ return parts.length === 0 ? [''] : parts;
+ }
+ // First phase: single-pattern processing
+ // <pre> is 1 or more portions
+ // <rest> is 1 or more portions
+ // <p> is any portion other than ., .., '', or **
+ // <e> is . or ''
+ //
+ // **/.. is *brutal* for filesystem walking performance, because
+ // it effectively resets the recursive walk each time it occurs,
+ // and ** cannot be reduced out by a .. pattern part like a regexp
+ // or most strings (other than .., ., and '') can be.
+ //
+ // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
+ // <pre>/<e>/<rest> -> <pre>/<rest>
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
+ // **/**/<rest> -> **/<rest>
+ //
+ // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
+ // this WOULD be allowed if ** did follow symlinks, or * didn't
+ firstPhasePreProcess(globParts) {
+ let didSomething = false;
+ do {
+ didSomething = false;
+ // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
+ for (let parts of globParts) {
+ let gs = -1;
+ while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
+ let gss = gs;
+ while (parts[gss + 1] === '**') {
+ // <pre>/**/**/<rest> -> <pre>/**/<rest>
+ gss++;
+ }
+ // eg, if gs is 2 and gss is 4, that means we have 3 **
+ // parts, and can remove 2 of them.
+ if (gss > gs) {
+ parts.splice(gs + 1, gss - gs);
+ }
+ let next = parts[gs + 1];
+ const p = parts[gs + 2];
+ const p2 = parts[gs + 3];
+ if (next !== '..')
+ continue;
+ if (!p ||
+ p === '.' ||
+ p === '..' ||
+ !p2 ||
+ p2 === '.' ||
+ p2 === '..') {
+ continue;
+ }
+ didSomething = true;
+ // edit parts in place, and push the new one
+ parts.splice(gs, 1);
+ const other = parts.slice(0);
+ other[gs] = '**';
+ globParts.push(other);
+ gs--;
+ }
+ // <pre>/<e>/<rest> -> <pre>/<rest>
+ if (!this.preserveMultipleSlashes) {
+ for (let i = 1; i < parts.length - 1; i++) {
+ const p = parts[i];
+ // don't squeeze out UNC patterns
+ if (i === 1 && p === '' && parts[0] === '')
+ continue;
+ if (p === '.' || p === '') {
+ didSomething = true;
+ parts.splice(i, 1);
+ i--;
+ }
+ }
+ if (parts[0] === '.' &&
+ parts.length === 2 &&
+ (parts[1] === '.' || parts[1] === '')) {
+ didSomething = true;
+ parts.pop();
+ }
+ }
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
+ let dd = 0;
+ while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
+ const p = parts[dd - 1];
+ if (p && p !== '.' && p !== '..' && p !== '**') {
+ didSomething = true;
+ const needDot = dd === 1 && parts[dd + 1] === '**';
+ const splin = needDot ? ['.'] : [];
+ parts.splice(dd - 1, 2, ...splin);
+ if (parts.length === 0)
+ parts.push('');
+ dd -= 2;
+ }
+ }
+ }
+ } while (didSomething);
+ return globParts;
+ }
+ // second phase: multi-pattern dedupes
+ // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
+ // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
+ // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
+ //
+ // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
+ // ^-- not valid because ** doens't follow symlinks
+ secondPhasePreProcess(globParts) {
+ for (let i = 0; i < globParts.length - 1; i++) {
+ for (let j = i + 1; j < globParts.length; j++) {
+ const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
+ if (!matched)
+ continue;
+ globParts[i] = matched;
+ globParts[j] = [];
+ }
+ }
+ return globParts.filter(gs => gs.length);
+ }
+ partsMatch(a, b, emptyGSMatch = false) {
+ let ai = 0;
+ let bi = 0;
+ let result = [];
+ let which = '';
+ while (ai < a.length && bi < b.length) {
+ if (a[ai] === b[bi]) {
+ result.push(which === 'b' ? b[bi] : a[ai]);
+ ai++;
+ bi++;
+ }
+ else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
+ result.push(a[ai]);
+ ai++;
+ }
+ else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
+ result.push(b[bi]);
+ bi++;
+ }
+ else if (a[ai] === '*' &&
+ b[bi] &&
+ (this.options.dot || !b[bi].startsWith('.')) &&
+ b[bi] !== '**') {
+ if (which === 'b')
+ return false;
+ which = 'a';
+ result.push(a[ai]);
+ ai++;
+ bi++;
+ }
+ else if (b[bi] === '*' &&
+ a[ai] &&
+ (this.options.dot || !a[ai].startsWith('.')) &&
+ a[ai] !== '**') {
+ if (which === 'a')
+ return false;
+ which = 'b';
+ result.push(b[bi]);
+ ai++;
+ bi++;
+ }
+ else {
+ return false;
+ }
+ }
+ // if we fall out of the loop, it means they two are identical
+ // as long as their lengths match
+ return a.length === b.length && result;
+ }
+ parseNegate() {
+ if (this.nonegate)
+ return;
+ const pattern = this.pattern;
+ let negate = false;
+ let negateOffset = 0;
+ for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
+ negate = !negate;
+ negateOffset++;
+ }
+ if (negateOffset)
+ this.pattern = pattern.slice(negateOffset);
+ this.negate = negate;
+ }
+ // set partial to true to test if, for example,
+ // "/a/b" matches the start of "/*/b/*/d"
+ // Partial means, if you run out of file before you run
+ // out of pattern, then that's fine, as long as all
+ // the parts match.
+ matchOne(file, pattern, partial = false) {
+ const options = this.options;
+ // UNC paths like //?/X:/... can match X:/... and vice versa
+ // Drive letters in absolute drive or unc paths are always compared
+ // case-insensitively.
+ if (this.isWindows) {
+ const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
+ const fileUNC = !fileDrive &&
+ file[0] === '' &&
+ file[1] === '' &&
+ file[2] === '?' &&
+ /^[a-z]:$/i.test(file[3]);
+ const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]);
+ const patternUNC = !patternDrive &&
+ pattern[0] === '' &&
+ pattern[1] === '' &&
+ pattern[2] === '?' &&
+ typeof pattern[3] === 'string' &&
+ /^[a-z]:$/i.test(pattern[3]);
+ const fdi = fileUNC ? 3 : fileDrive ? 0 : undefined;
+ const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined;
+ if (typeof fdi === 'number' && typeof pdi === 'number') {
+ const [fd, pd] = [file[fdi], pattern[pdi]];
+ if (fd.toLowerCase() === pd.toLowerCase()) {
+ pattern[pdi] = fd;
+ if (pdi > fdi) {
+ pattern = pattern.slice(pdi);
+ }
+ else if (fdi > pdi) {
+ file = file.slice(fdi);
+ }
+ }
+ }
+ }
+ // resolve and reduce . and .. portions in the file as well.
+ // dont' need to do the second phase, because it's only one string[]
+ const { optimizationLevel = 1 } = this.options;
+ if (optimizationLevel >= 2) {
+ file = this.levelTwoFileOptimize(file);
+ }
+ this.debug('matchOne', this, { file, pattern });
+ this.debug('matchOne', file.length, pattern.length);
+ for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
+ this.debug('matchOne loop');
+ var p = pattern[pi];
+ var f = file[fi];
+ this.debug(pattern, p, f);
+ // should be impossible.
+ // some invalid regexp stuff in the set.
+ /* c8 ignore start */
+ if (p === false) {
+ return false;
+ }
+ /* c8 ignore stop */
+ if (p === GLOBSTAR) {
+ this.debug('GLOBSTAR', [pattern, p, f]);
+ // "**"
+ // a/**/b/**/c would match the following:
+ // a/b/x/y/z/c
+ // a/x/y/z/b/c
+ // a/b/x/b/x/c
+ // a/b/c
+ // To do this, take the rest of the pattern after
+ // the **, and see if it would match the file remainder.
+ // If so, return success.
+ // If not, the ** "swallows" a segment, and try again.
+ // This is recursively awful.
+ //
+ // a/**/b/**/c matching a/b/x/y/z/c
+ // - a matches a
+ // - doublestar
+ // - matchOne(b/x/y/z/c, b/**/c)
+ // - b matches b
+ // - doublestar
+ // - matchOne(x/y/z/c, c) -> no
+ // - matchOne(y/z/c, c) -> no
+ // - matchOne(z/c, c) -> no
+ // - matchOne(c, c) yes, hit
+ var fr = fi;
+ var pr = pi + 1;
+ if (pr === pl) {
+ this.debug('** at the end');
+ // a ** at the end will just swallow the rest.
+ // We have found a match.
+ // however, it will not swallow /.x, unless
+ // options.dot is set.
+ // . and .. are *never* matched by **, for explosively
+ // exponential reasons.
+ for (; fi < fl; fi++) {
+ if (file[fi] === '.' ||
+ file[fi] === '..' ||
+ (!options.dot && file[fi].charAt(0) === '.'))
+ return false;
+ }
+ return true;
+ }
+ // ok, let's see if we can swallow whatever we can.
+ while (fr < fl) {
+ var swallowee = file[fr];
+ this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
+ // XXX remove this slice. Just pass the start index.
+ if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
+ this.debug('globstar found match!', fr, fl, swallowee);
+ // found a match.
+ return true;
+ }
+ else {
+ // can't swallow "." or ".." ever.
+ // can only swallow ".foo" when explicitly asked.
+ if (swallowee === '.' ||
+ swallowee === '..' ||
+ (!options.dot && swallowee.charAt(0) === '.')) {
+ this.debug('dot detected!', file, fr, pattern, pr);
+ break;
+ }
+ // ** swallows a segment, and continue.
+ this.debug('globstar swallow a segment, and continue');
+ fr++;
+ }
+ }
+ // no match was found.
+ // However, in partial mode, we can't say this is necessarily over.
+ /* c8 ignore start */
+ if (partial) {
+ // ran out of file
+ this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
+ if (fr === fl) {
+ return true;
+ }
+ }
+ /* c8 ignore stop */
+ return false;
+ }
+ // something other than **
+ // non-magic patterns just have to match exactly
+ // patterns with magic have been turned into regexps.
+ let hit;
+ if (typeof p === 'string') {
+ hit = f === p;
+ this.debug('string match', p, f, hit);
+ }
+ else {
+ hit = p.test(f);
+ this.debug('pattern match', p, f, hit);
+ }
+ if (!hit)
+ return false;
+ }
+ // Note: ending in / means that we'll get a final ""
+ // at the end of the pattern. This can only match a
+ // corresponding "" at the end of the file.
+ // If the file ends in /, then it can only match a
+ // a pattern that ends in /, unless the pattern just
+ // doesn't have any more for it. But, a/b/ should *not*
+ // match "a/b/*", even though "" matches against the
+ // [^/]*? pattern, except in partial mode, where it might
+ // simply not be reached yet.
+ // However, a/b/ should still satisfy a/*
+ // now either we fell off the end of the pattern, or we're done.
+ if (fi === fl && pi === pl) {
+ // ran out of pattern and filename at the same time.
+ // an exact hit!
+ return true;
+ }
+ else if (fi === fl) {
+ // ran out of file, but still had pattern left.
+ // this is ok if we're doing the match as part of
+ // a glob fs traversal.
+ return partial;
+ }
+ else if (pi === pl) {
+ // ran out of pattern, still have file left.
+ // this is only acceptable if we're on the very last
+ // empty segment of a file with a trailing slash.
+ // a/* should match a/b/
+ return fi === fl - 1 && file[fi] === '';
+ /* c8 ignore start */
+ }
+ else {
+ // should be unreachable.
+ throw new Error('wtf?');
+ }
+ /* c8 ignore stop */
+ }
+ braceExpand() {
+ return braceExpand(this.pattern, this.options);
+ }
+ parse(pattern) {
+ assertValidPattern(pattern);
+ const options = this.options;
+ // shortcuts
+ if (pattern === '**')
+ return GLOBSTAR;
+ if (pattern === '')
+ return '';
+ // far and away, the most common glob pattern parts are
+ // *, *.*, and *.<ext> Add a fast check method for those.
+ let m;
+ let fastTest = null;
+ if ((m = pattern.match(starRE))) {
+ fastTest = options.dot ? starTestDot : starTest;
+ }
+ else if ((m = pattern.match(starDotExtRE))) {
+ fastTest = (options.nocase
+ ? options.dot
+ ? starDotExtTestNocaseDot
+ : starDotExtTestNocase
+ : options.dot
+ ? starDotExtTestDot
+ : starDotExtTest)(m[1]);
+ }
+ else if ((m = pattern.match(qmarksRE))) {
+ fastTest = (options.nocase
+ ? options.dot
+ ? qmarksTestNocaseDot
+ : qmarksTestNocase
+ : options.dot
+ ? qmarksTestDot
+ : qmarksTest)(m);
+ }
+ else if ((m = pattern.match(starDotStarRE))) {
+ fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
+ }
+ else if ((m = pattern.match(dotStarRE))) {
+ fastTest = dotStarTest;
+ }
+ const re = AST.fromGlob(pattern, this.options).toMMPattern();
+ return fastTest ? Object.assign(re, { test: fastTest }) : re;
+ }
+ makeRe() {
+ if (this.regexp || this.regexp === false)
+ return this.regexp;
+ // at this point, this.set is a 2d array of partial
+ // pattern strings, or "**".
+ //
+ // It's better to use .match(). This function shouldn't
+ // be used, really, but it's pretty convenient sometimes,
+ // when you just want to work with a regex.
+ const set = this.set;
+ if (!set.length) {
+ this.regexp = false;
+ return this.regexp;
+ }
+ const options = this.options;
+ const twoStar = options.noglobstar
+ ? star
+ : options.dot
+ ? twoStarDot
+ : twoStarNoDot;
+ const flags = new Set(options.nocase ? ['i'] : []);
+ // 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 = pattern.map(p => {
+ if (p instanceof RegExp) {
+ for (const f of p.flags.split(''))
+ flags.add(f);
+ }
+ return typeof p === 'string'
+ ? regExpEscape(p)
+ : p === GLOBSTAR
+ ? GLOBSTAR
+ : p._src;
+ });
+ pp.forEach((p, i) => {
+ const next = pp[i + 1];
+ const prev = pp[i - 1];
+ if (p !== GLOBSTAR || prev === GLOBSTAR) {
+ return;
+ }
+ if (prev === undefined) {
+ if (next !== undefined && next !== GLOBSTAR) {
+ pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
+ }
+ else {
+ pp[i] = twoStar;
+ }
+ }
+ else if (next === undefined) {
+ pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?';
+ }
+ else if (next !== GLOBSTAR) {
+ pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
+ pp[i + 1] = GLOBSTAR;
+ }
+ });
+ return pp.filter(p => p !== GLOBSTAR).join('/');
+ })
+ .join('|');
+ // need to wrap in parens if we had more than one thing with |,
+ // otherwise only the first will be anchored to ^ and the last to $
+ const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
+ // must match entire pattern
+ // ending in a * or ** will make it less strict.
+ re = '^' + open + re + close + '$';
+ // can match anything, as long as it's not this.
+ if (this.negate)
+ re = '^(?!' + re + ').+$';
+ try {
+ this.regexp = new RegExp(re, [...flags].join(''));
+ /* c8 ignore start */
+ }
+ catch (ex) {
+ // should be impossible
+ this.regexp = false;
+ }
+ /* c8 ignore stop */
+ return this.regexp;
+ }
+ slashSplit(p) {
+ // if p starts with // on windows, we preserve that
+ // so that UNC paths aren't broken. Otherwise, any number of
+ // / characters are coalesced into one, unless
+ // preserveMultipleSlashes is set to true.
+ if (this.preserveMultipleSlashes) {
+ return p.split('/');
+ }
+ else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
+ // add an extra '' for the one we lose
+ return ['', ...p.split(/\/+/)];
+ }
+ else {
+ return p.split(/\/+/);
+ }
+ }
+ match(f, partial = this.partial) {
+ this.debug('match', f, this.pattern);
+ // short-circuit in the case of busted things.
+ // comments, etc.
+ if (this.comment) {
+ return false;
+ }
+ if (this.empty) {
+ return f === '';
+ }
+ if (f === '/' && partial) {
+ return true;
+ }
+ const options = this.options;
+ // windows: need to use /, not \
+ if (this.isWindows) {
+ f = f.split('\\').join('/');
+ }
+ // treat the test path as a set of pathparts.
+ const ff = this.slashSplit(f);
+ this.debug(this.pattern, 'split', ff);
+ // just ONE of the pattern sets in this.set needs to match
+ // in order for it to be valid. If negating, then just one
+ // match means that we have failed.
+ // Either way, return on the first hit.
+ const set = this.set;
+ this.debug(this.pattern, 'set', set);
+ // Find the basename of the path by looking for the last non-empty segment
+ let filename = ff[ff.length - 1];
+ if (!filename) {
+ for (let i = ff.length - 2; !filename && i >= 0; i--) {
+ filename = ff[i];
+ }
+ }
+ for (let i = 0; i < set.length; i++) {
+ const pattern = set[i];
+ let file = ff;
+ if (options.matchBase && pattern.length === 1) {
+ file = [filename];
+ }
+ const hit = this.matchOne(file, pattern, partial);
+ if (hit) {
+ if (options.flipNegate) {
+ return true;
+ }
+ return !this.negate;
+ }
+ }
+ // didn't get any hits. this is success if it's a negative
+ // pattern, failure otherwise.
+ if (options.flipNegate) {
+ return false;
+ }
+ return this.negate;
+ }
+ static defaults(def) {
+ return minimatch.defaults(def).Minimatch;
+ }
+}
+/* c8 ignore start */
+export { AST } from './ast.js';
+export { escape } from './escape.js';
+export { unescape } from './unescape.js';
+/* c8 ignore stop */
+minimatch.AST = AST;
+minimatch.Minimatch = Minimatch;
+minimatch.escape = escape;
+minimatch.unescape = unescape;
+//# sourceMappingURL=index.js.map \ No newline at end of file