1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3    return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.unescape = exports.escape = exports.AST = exports.Minimatch = exports.match = exports.makeRe = exports.braceExpand = exports.defaults = exports.filter = exports.GLOBSTAR = exports.sep = exports.minimatch = void 0;
7const brace_expansion_1 = __importDefault(require("brace-expansion"));
8const assert_valid_pattern_js_1 = require("./assert-valid-pattern.js");
9const ast_js_1 = require("./ast.js");
10const escape_js_1 = require("./escape.js");
11const unescape_js_1 = require("./unescape.js");
12const minimatch = (p, pattern, options = {}) => {
13    (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
14    // shortcut: comments match nothing.
15    if (!options.nocomment && pattern.charAt(0) === '#') {
16        return false;
17    }
18    return new Minimatch(pattern, options).match(p);
19};
20exports.minimatch = minimatch;
21// Optimized checking for the most common glob patterns.
22const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
23const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
24const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
25const starDotExtTestNocase = (ext) => {
26    ext = ext.toLowerCase();
27    return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
28};
29const starDotExtTestNocaseDot = (ext) => {
30    ext = ext.toLowerCase();
31    return (f) => f.toLowerCase().endsWith(ext);
32};
33const starDotStarRE = /^\*+\.\*+$/;
34const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
35const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
36const dotStarRE = /^\.\*+$/;
37const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
38const starRE = /^\*+$/;
39const starTest = (f) => f.length !== 0 && !f.startsWith('.');
40const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
41const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
42const qmarksTestNocase = ([$0, ext = '']) => {
43    const noext = qmarksTestNoExt([$0]);
44    if (!ext)
45        return noext;
46    ext = ext.toLowerCase();
47    return (f) => noext(f) && f.toLowerCase().endsWith(ext);
48};
49const qmarksTestNocaseDot = ([$0, ext = '']) => {
50    const noext = qmarksTestNoExtDot([$0]);
51    if (!ext)
52        return noext;
53    ext = ext.toLowerCase();
54    return (f) => noext(f) && f.toLowerCase().endsWith(ext);
55};
56const qmarksTestDot = ([$0, ext = '']) => {
57    const noext = qmarksTestNoExtDot([$0]);
58    return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
59};
60const qmarksTest = ([$0, ext = '']) => {
61    const noext = qmarksTestNoExt([$0]);
62    return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
63};
64const qmarksTestNoExt = ([$0]) => {
65    const len = $0.length;
66    return (f) => f.length === len && !f.startsWith('.');
67};
68const qmarksTestNoExtDot = ([$0]) => {
69    const len = $0.length;
70    return (f) => f.length === len && f !== '.' && f !== '..';
71};
72/* c8 ignore start */
73const defaultPlatform = (typeof process === 'object' && process
74    ? (typeof process.env === 'object' &&
75        process.env &&
76        process.env.__MINIMATCH_TESTING_PLATFORM__) ||
77        process.platform
78    : 'posix');
79const path = {
80    win32: { sep: '\\' },
81    posix: { sep: '/' },
82};
83/* c8 ignore stop */
84exports.sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep;
85exports.minimatch.sep = exports.sep;
86exports.GLOBSTAR = Symbol('globstar **');
87exports.minimatch.GLOBSTAR = exports.GLOBSTAR;
88// any single thing other than /
89// don't need to escape / when using new RegExp()
90const qmark = '[^/]';
91// * => any number of characters
92const star = qmark + '*?';
93// ** when dots are allowed.  Anything goes, except .. and .
94// not (^ or / followed by one or two dots followed by $ or /),
95// followed by anything, any number of times.
96const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
97// not a ^ or / followed by a dot,
98// followed by anything, any number of times.
99const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
100const filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options);
101exports.filter = filter;
102exports.minimatch.filter = exports.filter;
103const ext = (a, b = {}) => Object.assign({}, a, b);
104const defaults = (def) => {
105    if (!def || typeof def !== 'object' || !Object.keys(def).length) {
106        return exports.minimatch;
107    }
108    const orig = exports.minimatch;
109    const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
110    return Object.assign(m, {
111        Minimatch: class Minimatch extends orig.Minimatch {
112            constructor(pattern, options = {}) {
113                super(pattern, ext(def, options));
114            }
115            static defaults(options) {
116                return orig.defaults(ext(def, options)).Minimatch;
117            }
118        },
119        AST: class AST extends orig.AST {
120            /* c8 ignore start */
121            constructor(type, parent, options = {}) {
122                super(type, parent, ext(def, options));
123            }
124            /* c8 ignore stop */
125            static fromGlob(pattern, options = {}) {
126                return orig.AST.fromGlob(pattern, ext(def, options));
127            }
128        },
129        unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
130        escape: (s, options = {}) => orig.escape(s, ext(def, options)),
131        filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
132        defaults: (options) => orig.defaults(ext(def, options)),
133        makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
134        braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
135        match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
136        sep: orig.sep,
137        GLOBSTAR: exports.GLOBSTAR,
138    });
139};
140exports.defaults = defaults;
141exports.minimatch.defaults = exports.defaults;
142// Brace expansion:
143// a{b,c}d -> abd acd
144// a{b,}c -> abc ac
145// a{0..3}d -> a0d a1d a2d a3d
146// a{b,c{d,e}f}g -> abg acdfg acefg
147// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
148//
149// Invalid sets are not expanded.
150// a{2..}b -> a{2..}b
151// a{b}c -> a{b}c
152const braceExpand = (pattern, options = {}) => {
153    (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
154    // Thanks to Yeting Li <https://github.com/yetingli> for
155    // improving this regexp to avoid a ReDOS vulnerability.
156    if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
157        // shortcut. no need to expand.
158        return [pattern];
159    }
160    return (0, brace_expansion_1.default)(pattern);
161};
162exports.braceExpand = braceExpand;
163exports.minimatch.braceExpand = exports.braceExpand;
164// parse a component of the expanded set.
165// At this point, no pattern may contain "/" in it
166// so we're going to return a 2d array, where each entry is the full
167// pattern, split on '/', and then turned into a regular expression.
168// A regexp is made at the end which joins each array with an
169// escaped /, and another full one which joins each regexp with |.
170//
171// Following the lead of Bash 4.1, note that "**" only has special meaning
172// when it is the *only* thing in a path portion.  Otherwise, any series
173// of * is equivalent to a single *.  Globstar behavior is enabled by
174// default, and can be disabled by setting options.noglobstar.
175const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
176exports.makeRe = makeRe;
177exports.minimatch.makeRe = exports.makeRe;
178const match = (list, pattern, options = {}) => {
179    const mm = new Minimatch(pattern, options);
180    list = list.filter(f => mm.match(f));
181    if (mm.options.nonull && !list.length) {
182        list.push(pattern);
183    }
184    return list;
185};
186exports.match = match;
187exports.minimatch.match = exports.match;
188// replace stuff like \* with *
189const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
190const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
191class Minimatch {
192    options;
193    set;
194    pattern;
195    windowsPathsNoEscape;
196    nonegate;
197    negate;
198    comment;
199    empty;
200    preserveMultipleSlashes;
201    partial;
202    globSet;
203    globParts;
204    nocase;
205    isWindows;
206    platform;
207    windowsNoMagicRoot;
208    regexp;
209    constructor(pattern, options = {}) {
210        (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
211        options = options || {};
212        this.options = options;
213        this.pattern = pattern;
214        this.platform = options.platform || defaultPlatform;
215        this.isWindows = this.platform === 'win32';
216        this.windowsPathsNoEscape =
217            !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
218        if (this.windowsPathsNoEscape) {
219            this.pattern = this.pattern.replace(/\\/g, '/');
220        }
221        this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
222        this.regexp = null;
223        this.negate = false;
224        this.nonegate = !!options.nonegate;
225        this.comment = false;
226        this.empty = false;
227        this.partial = !!options.partial;
228        this.nocase = !!this.options.nocase;
229        this.windowsNoMagicRoot =
230            options.windowsNoMagicRoot !== undefined
231                ? options.windowsNoMagicRoot
232                : !!(this.isWindows && this.nocase);
233        this.globSet = [];
234        this.globParts = [];
235        this.set = [];
236        // make the set of regexps etc.
237        this.make();
238    }
239    hasMagic() {
240        if (this.options.magicalBraces && this.set.length > 1) {
241            return true;
242        }
243        for (const pattern of this.set) {
244            for (const part of pattern) {
245                if (typeof part !== 'string')
246                    return true;
247            }
248        }
249        return false;
250    }
251    debug(..._) { }
252    make() {
253        const pattern = this.pattern;
254        const options = this.options;
255        // empty patterns and comments match nothing.
256        if (!options.nocomment && pattern.charAt(0) === '#') {
257            this.comment = true;
258            return;
259        }
260        if (!pattern) {
261            this.empty = true;
262            return;
263        }
264        // step 1: figure out negation, etc.
265        this.parseNegate();
266        // step 2: expand braces
267        this.globSet = [...new Set(this.braceExpand())];
268        if (options.debug) {
269            this.debug = (...args) => console.error(...args);
270        }
271        this.debug(this.pattern, this.globSet);
272        // step 3: now we have a set, so turn each one into a series of
273        // path-portion matching patterns.
274        // These will be regexps, except in the case of "**", which is
275        // set to the GLOBSTAR object for globstar behavior,
276        // and will not contain any / characters
277        //
278        // First, we preprocess to make the glob pattern sets a bit simpler
279        // and deduped.  There are some perf-killing patterns that can cause
280        // problems with a glob walk, but we can simplify them down a bit.
281        const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
282        this.globParts = this.preprocess(rawGlobParts);
283        this.debug(this.pattern, this.globParts);
284        // glob --> regexps
285        let set = this.globParts.map((s, _, __) => {
286            if (this.isWindows && this.windowsNoMagicRoot) {
287                // check if it's a drive or unc path.
288                const isUNC = s[0] === '' &&
289                    s[1] === '' &&
290                    (s[2] === '?' || !globMagic.test(s[2])) &&
291                    !globMagic.test(s[3]);
292                const isDrive = /^[a-z]:/i.test(s[0]);
293                if (isUNC) {
294                    return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))];
295                }
296                else if (isDrive) {
297                    return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
298                }
299            }
300            return s.map(ss => this.parse(ss));
301        });
302        this.debug(this.pattern, set);
303        // filter out everything that didn't compile properly.
304        this.set = set.filter(s => s.indexOf(false) === -1);
305        // do not treat the ? in UNC paths as magic
306        if (this.isWindows) {
307            for (let i = 0; i < this.set.length; i++) {
308                const p = this.set[i];
309                if (p[0] === '' &&
310                    p[1] === '' &&
311                    this.globParts[i][2] === '?' &&
312                    typeof p[3] === 'string' &&
313                    /^[a-z]:$/i.test(p[3])) {
314                    p[2] = '?';
315                }
316            }
317        }
318        this.debug(this.pattern, this.set);
319    }
320    // various transforms to equivalent pattern sets that are
321    // faster to process in a filesystem walk.  The goal is to
322    // eliminate what we can, and push all ** patterns as far
323    // to the right as possible, even if it increases the number
324    // of patterns that we have to process.
325    preprocess(globParts) {
326        // if we're not in globstar mode, then turn all ** into *
327        if (this.options.noglobstar) {
328            for (let i = 0; i < globParts.length; i++) {
329                for (let j = 0; j < globParts[i].length; j++) {
330                    if (globParts[i][j] === '**') {
331                        globParts[i][j] = '*';
332                    }
333                }
334            }
335        }
336        const { optimizationLevel = 1 } = this.options;
337        if (optimizationLevel >= 2) {
338            // aggressive optimization for the purpose of fs walking
339            globParts = this.firstPhasePreProcess(globParts);
340            globParts = this.secondPhasePreProcess(globParts);
341        }
342        else if (optimizationLevel >= 1) {
343            // just basic optimizations to remove some .. parts
344            globParts = this.levelOneOptimize(globParts);
345        }
346        else {
347            globParts = this.adjascentGlobstarOptimize(globParts);
348        }
349        return globParts;
350    }
351    // just get rid of adjascent ** portions
352    adjascentGlobstarOptimize(globParts) {
353        return globParts.map(parts => {
354            let gs = -1;
355            while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
356                let i = gs;
357                while (parts[i + 1] === '**') {
358                    i++;
359                }
360                if (i !== gs) {
361                    parts.splice(gs, i - gs);
362                }
363            }
364            return parts;
365        });
366    }
367    // get rid of adjascent ** and resolve .. portions
368    levelOneOptimize(globParts) {
369        return globParts.map(parts => {
370            parts = parts.reduce((set, part) => {
371                const prev = set[set.length - 1];
372                if (part === '**' && prev === '**') {
373                    return set;
374                }
375                if (part === '..') {
376                    if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
377                        set.pop();
378                        return set;
379                    }
380                }
381                set.push(part);
382                return set;
383            }, []);
384            return parts.length === 0 ? [''] : parts;
385        });
386    }
387    levelTwoFileOptimize(parts) {
388        if (!Array.isArray(parts)) {
389            parts = this.slashSplit(parts);
390        }
391        let didSomething = false;
392        do {
393            didSomething = false;
394            // <pre>/<e>/<rest> -> <pre>/<rest>
395            if (!this.preserveMultipleSlashes) {
396                for (let i = 1; i < parts.length - 1; i++) {
397                    const p = parts[i];
398                    // don't squeeze out UNC patterns
399                    if (i === 1 && p === '' && parts[0] === '')
400                        continue;
401                    if (p === '.' || p === '') {
402                        didSomething = true;
403                        parts.splice(i, 1);
404                        i--;
405                    }
406                }
407                if (parts[0] === '.' &&
408                    parts.length === 2 &&
409                    (parts[1] === '.' || parts[1] === '')) {
410                    didSomething = true;
411                    parts.pop();
412                }
413            }
414            // <pre>/<p>/../<rest> -> <pre>/<rest>
415            let dd = 0;
416            while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
417                const p = parts[dd - 1];
418                if (p && p !== '.' && p !== '..' && p !== '**') {
419                    didSomething = true;
420                    parts.splice(dd - 1, 2);
421                    dd -= 2;
422                }
423            }
424        } while (didSomething);
425        return parts.length === 0 ? [''] : parts;
426    }
427    // First phase: single-pattern processing
428    // <pre> is 1 or more portions
429    // <rest> is 1 or more portions
430    // <p> is any portion other than ., .., '', or **
431    // <e> is . or ''
432    //
433    // **/.. is *brutal* for filesystem walking performance, because
434    // it effectively resets the recursive walk each time it occurs,
435    // and ** cannot be reduced out by a .. pattern part like a regexp
436    // or most strings (other than .., ., and '') can be.
437    //
438    // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
439    // <pre>/<e>/<rest> -> <pre>/<rest>
440    // <pre>/<p>/../<rest> -> <pre>/<rest>
441    // **/**/<rest> -> **/<rest>
442    //
443    // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
444    // this WOULD be allowed if ** did follow symlinks, or * didn't
445    firstPhasePreProcess(globParts) {
446        let didSomething = false;
447        do {
448            didSomething = false;
449            // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
450            for (let parts of globParts) {
451                let gs = -1;
452                while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
453                    let gss = gs;
454                    while (parts[gss + 1] === '**') {
455                        // <pre>/**/**/<rest> -> <pre>/**/<rest>
456                        gss++;
457                    }
458                    // eg, if gs is 2 and gss is 4, that means we have 3 **
459                    // parts, and can remove 2 of them.
460                    if (gss > gs) {
461                        parts.splice(gs + 1, gss - gs);
462                    }
463                    let next = parts[gs + 1];
464                    const p = parts[gs + 2];
465                    const p2 = parts[gs + 3];
466                    if (next !== '..')
467                        continue;
468                    if (!p ||
469                        p === '.' ||
470                        p === '..' ||
471                        !p2 ||
472                        p2 === '.' ||
473                        p2 === '..') {
474                        continue;
475                    }
476                    didSomething = true;
477                    // edit parts in place, and push the new one
478                    parts.splice(gs, 1);
479                    const other = parts.slice(0);
480                    other[gs] = '**';
481                    globParts.push(other);
482                    gs--;
483                }
484                // <pre>/<e>/<rest> -> <pre>/<rest>
485                if (!this.preserveMultipleSlashes) {
486                    for (let i = 1; i < parts.length - 1; i++) {
487                        const p = parts[i];
488                        // don't squeeze out UNC patterns
489                        if (i === 1 && p === '' && parts[0] === '')
490                            continue;
491                        if (p === '.' || p === '') {
492                            didSomething = true;
493                            parts.splice(i, 1);
494                            i--;
495                        }
496                    }
497                    if (parts[0] === '.' &&
498                        parts.length === 2 &&
499                        (parts[1] === '.' || parts[1] === '')) {
500                        didSomething = true;
501                        parts.pop();
502                    }
503                }
504                // <pre>/<p>/../<rest> -> <pre>/<rest>
505                let dd = 0;
506                while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
507                    const p = parts[dd - 1];
508                    if (p && p !== '.' && p !== '..' && p !== '**') {
509                        didSomething = true;
510                        const needDot = dd === 1 && parts[dd + 1] === '**';
511                        const splin = needDot ? ['.'] : [];
512                        parts.splice(dd - 1, 2, ...splin);
513                        if (parts.length === 0)
514                            parts.push('');
515                        dd -= 2;
516                    }
517                }
518            }
519        } while (didSomething);
520        return globParts;
521    }
522    // second phase: multi-pattern dedupes
523    // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
524    // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
525    // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
526    //
527    // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
528    // ^-- not valid because ** doens't follow symlinks
529    secondPhasePreProcess(globParts) {
530        for (let i = 0; i < globParts.length - 1; i++) {
531            for (let j = i + 1; j < globParts.length; j++) {
532                const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
533                if (!matched)
534                    continue;
535                globParts[i] = matched;
536                globParts[j] = [];
537            }
538        }
539        return globParts.filter(gs => gs.length);
540    }
541    partsMatch(a, b, emptyGSMatch = false) {
542        let ai = 0;
543        let bi = 0;
544        let result = [];
545        let which = '';
546        while (ai < a.length && bi < b.length) {
547            if (a[ai] === b[bi]) {
548                result.push(which === 'b' ? b[bi] : a[ai]);
549                ai++;
550                bi++;
551            }
552            else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
553                result.push(a[ai]);
554                ai++;
555            }
556            else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
557                result.push(b[bi]);
558                bi++;
559            }
560            else if (a[ai] === '*' &&
561                b[bi] &&
562                (this.options.dot || !b[bi].startsWith('.')) &&
563                b[bi] !== '**') {
564                if (which === 'b')
565                    return false;
566                which = 'a';
567                result.push(a[ai]);
568                ai++;
569                bi++;
570            }
571            else if (b[bi] === '*' &&
572                a[ai] &&
573                (this.options.dot || !a[ai].startsWith('.')) &&
574                a[ai] !== '**') {
575                if (which === 'a')
576                    return false;
577                which = 'b';
578                result.push(b[bi]);
579                ai++;
580                bi++;
581            }
582            else {
583                return false;
584            }
585        }
586        // if we fall out of the loop, it means they two are identical
587        // as long as their lengths match
588        return a.length === b.length && result;
589    }
590    parseNegate() {
591        if (this.nonegate)
592            return;
593        const pattern = this.pattern;
594        let negate = false;
595        let negateOffset = 0;
596        for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
597            negate = !negate;
598            negateOffset++;
599        }
600        if (negateOffset)
601            this.pattern = pattern.slice(negateOffset);
602        this.negate = negate;
603    }
604    // set partial to true to test if, for example,
605    // "/a/b" matches the start of "/*/b/*/d"
606    // Partial means, if you run out of file before you run
607    // out of pattern, then that's fine, as long as all
608    // the parts match.
609    matchOne(file, pattern, partial = false) {
610        const options = this.options;
611        // UNC paths like //?/X:/... can match X:/... and vice versa
612        // Drive letters in absolute drive or unc paths are always compared
613        // case-insensitively.
614        if (this.isWindows) {
615            const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
616            const fileUNC = !fileDrive &&
617                file[0] === '' &&
618                file[1] === '' &&
619                file[2] === '?' &&
620                /^[a-z]:$/i.test(file[3]);
621            const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]);
622            const patternUNC = !patternDrive &&
623                pattern[0] === '' &&
624                pattern[1] === '' &&
625                pattern[2] === '?' &&
626                typeof pattern[3] === 'string' &&
627                /^[a-z]:$/i.test(pattern[3]);
628            const fdi = fileUNC ? 3 : fileDrive ? 0 : undefined;
629            const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined;
630            if (typeof fdi === 'number' && typeof pdi === 'number') {
631                const [fd, pd] = [file[fdi], pattern[pdi]];
632                if (fd.toLowerCase() === pd.toLowerCase()) {
633                    pattern[pdi] = fd;
634                    if (pdi > fdi) {
635                        pattern = pattern.slice(pdi);
636                    }
637                    else if (fdi > pdi) {
638                        file = file.slice(fdi);
639                    }
640                }
641            }
642        }
643        // resolve and reduce . and .. portions in the file as well.
644        // dont' need to do the second phase, because it's only one string[]
645        const { optimizationLevel = 1 } = this.options;
646        if (optimizationLevel >= 2) {
647            file = this.levelTwoFileOptimize(file);
648        }
649        this.debug('matchOne', this, { file, pattern });
650        this.debug('matchOne', file.length, pattern.length);
651        for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
652            this.debug('matchOne loop');
653            var p = pattern[pi];
654            var f = file[fi];
655            this.debug(pattern, p, f);
656            // should be impossible.
657            // some invalid regexp stuff in the set.
658            /* c8 ignore start */
659            if (p === false) {
660                return false;
661            }
662            /* c8 ignore stop */
663            if (p === exports.GLOBSTAR) {
664                this.debug('GLOBSTAR', [pattern, p, f]);
665                // "**"
666                // a/**/b/**/c would match the following:
667                // a/b/x/y/z/c
668                // a/x/y/z/b/c
669                // a/b/x/b/x/c
670                // a/b/c
671                // To do this, take the rest of the pattern after
672                // the **, and see if it would match the file remainder.
673                // If so, return success.
674                // If not, the ** "swallows" a segment, and try again.
675                // This is recursively awful.
676                //
677                // a/**/b/**/c matching a/b/x/y/z/c
678                // - a matches a
679                // - doublestar
680                //   - matchOne(b/x/y/z/c, b/**/c)
681                //     - b matches b
682                //     - doublestar
683                //       - matchOne(x/y/z/c, c) -> no
684                //       - matchOne(y/z/c, c) -> no
685                //       - matchOne(z/c, c) -> no
686                //       - matchOne(c, c) yes, hit
687                var fr = fi;
688                var pr = pi + 1;
689                if (pr === pl) {
690                    this.debug('** at the end');
691                    // a ** at the end will just swallow the rest.
692                    // We have found a match.
693                    // however, it will not swallow /.x, unless
694                    // options.dot is set.
695                    // . and .. are *never* matched by **, for explosively
696                    // exponential reasons.
697                    for (; fi < fl; fi++) {
698                        if (file[fi] === '.' ||
699                            file[fi] === '..' ||
700                            (!options.dot && file[fi].charAt(0) === '.'))
701                            return false;
702                    }
703                    return true;
704                }
705                // ok, let's see if we can swallow whatever we can.
706                while (fr < fl) {
707                    var swallowee = file[fr];
708                    this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
709                    // XXX remove this slice.  Just pass the start index.
710                    if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
711                        this.debug('globstar found match!', fr, fl, swallowee);
712                        // found a match.
713                        return true;
714                    }
715                    else {
716                        // can't swallow "." or ".." ever.
717                        // can only swallow ".foo" when explicitly asked.
718                        if (swallowee === '.' ||
719                            swallowee === '..' ||
720                            (!options.dot && swallowee.charAt(0) === '.')) {
721                            this.debug('dot detected!', file, fr, pattern, pr);
722                            break;
723                        }
724                        // ** swallows a segment, and continue.
725                        this.debug('globstar swallow a segment, and continue');
726                        fr++;
727                    }
728                }
729                // no match was found.
730                // However, in partial mode, we can't say this is necessarily over.
731                /* c8 ignore start */
732                if (partial) {
733                    // ran out of file
734                    this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
735                    if (fr === fl) {
736                        return true;
737                    }
738                }
739                /* c8 ignore stop */
740                return false;
741            }
742            // something other than **
743            // non-magic patterns just have to match exactly
744            // patterns with magic have been turned into regexps.
745            let hit;
746            if (typeof p === 'string') {
747                hit = f === p;
748                this.debug('string match', p, f, hit);
749            }
750            else {
751                hit = p.test(f);
752                this.debug('pattern match', p, f, hit);
753            }
754            if (!hit)
755                return false;
756        }
757        // Note: ending in / means that we'll get a final ""
758        // at the end of the pattern.  This can only match a
759        // corresponding "" at the end of the file.
760        // If the file ends in /, then it can only match a
761        // a pattern that ends in /, unless the pattern just
762        // doesn't have any more for it. But, a/b/ should *not*
763        // match "a/b/*", even though "" matches against the
764        // [^/]*? pattern, except in partial mode, where it might
765        // simply not be reached yet.
766        // However, a/b/ should still satisfy a/*
767        // now either we fell off the end of the pattern, or we're done.
768        if (fi === fl && pi === pl) {
769            // ran out of pattern and filename at the same time.
770            // an exact hit!
771            return true;
772        }
773        else if (fi === fl) {
774            // ran out of file, but still had pattern left.
775            // this is ok if we're doing the match as part of
776            // a glob fs traversal.
777            return partial;
778        }
779        else if (pi === pl) {
780            // ran out of pattern, still have file left.
781            // this is only acceptable if we're on the very last
782            // empty segment of a file with a trailing slash.
783            // a/* should match a/b/
784            return fi === fl - 1 && file[fi] === '';
785            /* c8 ignore start */
786        }
787        else {
788            // should be unreachable.
789            throw new Error('wtf?');
790        }
791        /* c8 ignore stop */
792    }
793    braceExpand() {
794        return (0, exports.braceExpand)(this.pattern, this.options);
795    }
796    parse(pattern) {
797        (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
798        const options = this.options;
799        // shortcuts
800        if (pattern === '**')
801            return exports.GLOBSTAR;
802        if (pattern === '')
803            return '';
804        // far and away, the most common glob pattern parts are
805        // *, *.*, and *.<ext>  Add a fast check method for those.
806        let m;
807        let fastTest = null;
808        if ((m = pattern.match(starRE))) {
809            fastTest = options.dot ? starTestDot : starTest;
810        }
811        else if ((m = pattern.match(starDotExtRE))) {
812            fastTest = (options.nocase
813                ? options.dot
814                    ? starDotExtTestNocaseDot
815                    : starDotExtTestNocase
816                : options.dot
817                    ? starDotExtTestDot
818                    : starDotExtTest)(m[1]);
819        }
820        else if ((m = pattern.match(qmarksRE))) {
821            fastTest = (options.nocase
822                ? options.dot
823                    ? qmarksTestNocaseDot
824                    : qmarksTestNocase
825                : options.dot
826                    ? qmarksTestDot
827                    : qmarksTest)(m);
828        }
829        else if ((m = pattern.match(starDotStarRE))) {
830            fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
831        }
832        else if ((m = pattern.match(dotStarRE))) {
833            fastTest = dotStarTest;
834        }
835        const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern();
836        return fastTest ? Object.assign(re, { test: fastTest }) : re;
837    }
838    makeRe() {
839        if (this.regexp || this.regexp === false)
840            return this.regexp;
841        // at this point, this.set is a 2d array of partial
842        // pattern strings, or "**".
843        //
844        // It's better to use .match().  This function shouldn't
845        // be used, really, but it's pretty convenient sometimes,
846        // when you just want to work with a regex.
847        const set = this.set;
848        if (!set.length) {
849            this.regexp = false;
850            return this.regexp;
851        }
852        const options = this.options;
853        const twoStar = options.noglobstar
854            ? star
855            : options.dot
856                ? twoStarDot
857                : twoStarNoDot;
858        const flags = new Set(options.nocase ? ['i'] : []);
859        // regexpify non-globstar patterns
860        // if ** is only item, then we just do one twoStar
861        // if ** is first, and there are more, prepend (\/|twoStar\/)? to next
862        // if ** is last, append (\/twoStar|) to previous
863        // if ** is in the middle, append (\/|\/twoStar\/) to previous
864        // then filter out GLOBSTAR symbols
865        let re = set
866            .map(pattern => {
867            const pp = pattern.map(p => {
868                if (p instanceof RegExp) {
869                    for (const f of p.flags.split(''))
870                        flags.add(f);
871                }
872                return typeof p === 'string'
873                    ? regExpEscape(p)
874                    : p === exports.GLOBSTAR
875                        ? exports.GLOBSTAR
876                        : p._src;
877            });
878            pp.forEach((p, i) => {
879                const next = pp[i + 1];
880                const prev = pp[i - 1];
881                if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) {
882                    return;
883                }
884                if (prev === undefined) {
885                    if (next !== undefined && next !== exports.GLOBSTAR) {
886                        pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
887                    }
888                    else {
889                        pp[i] = twoStar;
890                    }
891                }
892                else if (next === undefined) {
893                    pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?';
894                }
895                else if (next !== exports.GLOBSTAR) {
896                    pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
897                    pp[i + 1] = exports.GLOBSTAR;
898                }
899            });
900            return pp.filter(p => p !== exports.GLOBSTAR).join('/');
901        })
902            .join('|');
903        // need to wrap in parens if we had more than one thing with |,
904        // otherwise only the first will be anchored to ^ and the last to $
905        const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
906        // must match entire pattern
907        // ending in a * or ** will make it less strict.
908        re = '^' + open + re + close + '$';
909        // can match anything, as long as it's not this.
910        if (this.negate)
911            re = '^(?!' + re + ').+$';
912        try {
913            this.regexp = new RegExp(re, [...flags].join(''));
914            /* c8 ignore start */
915        }
916        catch (ex) {
917            // should be impossible
918            this.regexp = false;
919        }
920        /* c8 ignore stop */
921        return this.regexp;
922    }
923    slashSplit(p) {
924        // if p starts with // on windows, we preserve that
925        // so that UNC paths aren't broken.  Otherwise, any number of
926        // / characters are coalesced into one, unless
927        // preserveMultipleSlashes is set to true.
928        if (this.preserveMultipleSlashes) {
929            return p.split('/');
930        }
931        else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
932            // add an extra '' for the one we lose
933            return ['', ...p.split(/\/+/)];
934        }
935        else {
936            return p.split(/\/+/);
937        }
938    }
939    match(f, partial = this.partial) {
940        this.debug('match', f, this.pattern);
941        // short-circuit in the case of busted things.
942        // comments, etc.
943        if (this.comment) {
944            return false;
945        }
946        if (this.empty) {
947            return f === '';
948        }
949        if (f === '/' && partial) {
950            return true;
951        }
952        const options = this.options;
953        // windows: need to use /, not \
954        if (this.isWindows) {
955            f = f.split('\\').join('/');
956        }
957        // treat the test path as a set of pathparts.
958        const ff = this.slashSplit(f);
959        this.debug(this.pattern, 'split', ff);
960        // just ONE of the pattern sets in this.set needs to match
961        // in order for it to be valid.  If negating, then just one
962        // match means that we have failed.
963        // Either way, return on the first hit.
964        const set = this.set;
965        this.debug(this.pattern, 'set', set);
966        // Find the basename of the path by looking for the last non-empty segment
967        let filename = ff[ff.length - 1];
968        if (!filename) {
969            for (let i = ff.length - 2; !filename && i >= 0; i--) {
970                filename = ff[i];
971            }
972        }
973        for (let i = 0; i < set.length; i++) {
974            const pattern = set[i];
975            let file = ff;
976            if (options.matchBase && pattern.length === 1) {
977                file = [filename];
978            }
979            const hit = this.matchOne(file, pattern, partial);
980            if (hit) {
981                if (options.flipNegate) {
982                    return true;
983                }
984                return !this.negate;
985            }
986        }
987        // didn't get any hits.  this is success if it's a negative
988        // pattern, failure otherwise.
989        if (options.flipNegate) {
990            return false;
991        }
992        return this.negate;
993    }
994    static defaults(def) {
995        return exports.minimatch.defaults(def).Minimatch;
996    }
997}
998exports.Minimatch = Minimatch;
999/* c8 ignore start */
1000var ast_js_2 = require("./ast.js");
1001Object.defineProperty(exports, "AST", { enumerable: true, get: function () { return ast_js_2.AST; } });
1002var escape_js_2 = require("./escape.js");
1003Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } });
1004var unescape_js_2 = require("./unescape.js");
1005Object.defineProperty(exports, "unescape", { enumerable: true, get: function () { return unescape_js_2.unescape; } });
1006/* c8 ignore stop */
1007exports.minimatch.AST = ast_js_1.AST;
1008exports.minimatch.Minimatch = Minimatch;
1009exports.minimatch.escape = escape_js_1.escape;
1010exports.minimatch.unescape = unescape_js_1.unescape;
1011//# sourceMappingURL=index.js.map