11cb0ef41Sopenharmony_ciimport expand from 'brace-expansion'; 21cb0ef41Sopenharmony_ciimport { assertValidPattern } from './assert-valid-pattern.js'; 31cb0ef41Sopenharmony_ciimport { AST } from './ast.js'; 41cb0ef41Sopenharmony_ciimport { escape } from './escape.js'; 51cb0ef41Sopenharmony_ciimport { unescape } from './unescape.js'; 61cb0ef41Sopenharmony_ciexport const minimatch = (p, pattern, options = {}) => { 71cb0ef41Sopenharmony_ci assertValidPattern(pattern); 81cb0ef41Sopenharmony_ci // shortcut: comments match nothing. 91cb0ef41Sopenharmony_ci if (!options.nocomment && pattern.charAt(0) === '#') { 101cb0ef41Sopenharmony_ci return false; 111cb0ef41Sopenharmony_ci } 121cb0ef41Sopenharmony_ci return new Minimatch(pattern, options).match(p); 131cb0ef41Sopenharmony_ci}; 141cb0ef41Sopenharmony_ci// Optimized checking for the most common glob patterns. 151cb0ef41Sopenharmony_ciconst starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/; 161cb0ef41Sopenharmony_ciconst starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext); 171cb0ef41Sopenharmony_ciconst starDotExtTestDot = (ext) => (f) => f.endsWith(ext); 181cb0ef41Sopenharmony_ciconst starDotExtTestNocase = (ext) => { 191cb0ef41Sopenharmony_ci ext = ext.toLowerCase(); 201cb0ef41Sopenharmony_ci return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext); 211cb0ef41Sopenharmony_ci}; 221cb0ef41Sopenharmony_ciconst starDotExtTestNocaseDot = (ext) => { 231cb0ef41Sopenharmony_ci ext = ext.toLowerCase(); 241cb0ef41Sopenharmony_ci return (f) => f.toLowerCase().endsWith(ext); 251cb0ef41Sopenharmony_ci}; 261cb0ef41Sopenharmony_ciconst starDotStarRE = /^\*+\.\*+$/; 271cb0ef41Sopenharmony_ciconst starDotStarTest = (f) => !f.startsWith('.') && f.includes('.'); 281cb0ef41Sopenharmony_ciconst starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.'); 291cb0ef41Sopenharmony_ciconst dotStarRE = /^\.\*+$/; 301cb0ef41Sopenharmony_ciconst dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.'); 311cb0ef41Sopenharmony_ciconst starRE = /^\*+$/; 321cb0ef41Sopenharmony_ciconst starTest = (f) => f.length !== 0 && !f.startsWith('.'); 331cb0ef41Sopenharmony_ciconst starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..'; 341cb0ef41Sopenharmony_ciconst qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/; 351cb0ef41Sopenharmony_ciconst qmarksTestNocase = ([$0, ext = '']) => { 361cb0ef41Sopenharmony_ci const noext = qmarksTestNoExt([$0]); 371cb0ef41Sopenharmony_ci if (!ext) 381cb0ef41Sopenharmony_ci return noext; 391cb0ef41Sopenharmony_ci ext = ext.toLowerCase(); 401cb0ef41Sopenharmony_ci return (f) => noext(f) && f.toLowerCase().endsWith(ext); 411cb0ef41Sopenharmony_ci}; 421cb0ef41Sopenharmony_ciconst qmarksTestNocaseDot = ([$0, ext = '']) => { 431cb0ef41Sopenharmony_ci const noext = qmarksTestNoExtDot([$0]); 441cb0ef41Sopenharmony_ci if (!ext) 451cb0ef41Sopenharmony_ci return noext; 461cb0ef41Sopenharmony_ci ext = ext.toLowerCase(); 471cb0ef41Sopenharmony_ci return (f) => noext(f) && f.toLowerCase().endsWith(ext); 481cb0ef41Sopenharmony_ci}; 491cb0ef41Sopenharmony_ciconst qmarksTestDot = ([$0, ext = '']) => { 501cb0ef41Sopenharmony_ci const noext = qmarksTestNoExtDot([$0]); 511cb0ef41Sopenharmony_ci return !ext ? noext : (f) => noext(f) && f.endsWith(ext); 521cb0ef41Sopenharmony_ci}; 531cb0ef41Sopenharmony_ciconst qmarksTest = ([$0, ext = '']) => { 541cb0ef41Sopenharmony_ci const noext = qmarksTestNoExt([$0]); 551cb0ef41Sopenharmony_ci return !ext ? noext : (f) => noext(f) && f.endsWith(ext); 561cb0ef41Sopenharmony_ci}; 571cb0ef41Sopenharmony_ciconst qmarksTestNoExt = ([$0]) => { 581cb0ef41Sopenharmony_ci const len = $0.length; 591cb0ef41Sopenharmony_ci return (f) => f.length === len && !f.startsWith('.'); 601cb0ef41Sopenharmony_ci}; 611cb0ef41Sopenharmony_ciconst qmarksTestNoExtDot = ([$0]) => { 621cb0ef41Sopenharmony_ci const len = $0.length; 631cb0ef41Sopenharmony_ci return (f) => f.length === len && f !== '.' && f !== '..'; 641cb0ef41Sopenharmony_ci}; 651cb0ef41Sopenharmony_ci/* c8 ignore start */ 661cb0ef41Sopenharmony_ciconst defaultPlatform = (typeof process === 'object' && process 671cb0ef41Sopenharmony_ci ? (typeof process.env === 'object' && 681cb0ef41Sopenharmony_ci process.env && 691cb0ef41Sopenharmony_ci process.env.__MINIMATCH_TESTING_PLATFORM__) || 701cb0ef41Sopenharmony_ci process.platform 711cb0ef41Sopenharmony_ci : 'posix'); 721cb0ef41Sopenharmony_ciconst path = { 731cb0ef41Sopenharmony_ci win32: { sep: '\\' }, 741cb0ef41Sopenharmony_ci posix: { sep: '/' }, 751cb0ef41Sopenharmony_ci}; 761cb0ef41Sopenharmony_ci/* c8 ignore stop */ 771cb0ef41Sopenharmony_ciexport const sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep; 781cb0ef41Sopenharmony_ciminimatch.sep = sep; 791cb0ef41Sopenharmony_ciexport const GLOBSTAR = Symbol('globstar **'); 801cb0ef41Sopenharmony_ciminimatch.GLOBSTAR = GLOBSTAR; 811cb0ef41Sopenharmony_ci// any single thing other than / 821cb0ef41Sopenharmony_ci// don't need to escape / when using new RegExp() 831cb0ef41Sopenharmony_ciconst qmark = '[^/]'; 841cb0ef41Sopenharmony_ci// * => any number of characters 851cb0ef41Sopenharmony_ciconst star = qmark + '*?'; 861cb0ef41Sopenharmony_ci// ** when dots are allowed. Anything goes, except .. and . 871cb0ef41Sopenharmony_ci// not (^ or / followed by one or two dots followed by $ or /), 881cb0ef41Sopenharmony_ci// followed by anything, any number of times. 891cb0ef41Sopenharmony_ciconst twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?'; 901cb0ef41Sopenharmony_ci// not a ^ or / followed by a dot, 911cb0ef41Sopenharmony_ci// followed by anything, any number of times. 921cb0ef41Sopenharmony_ciconst twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?'; 931cb0ef41Sopenharmony_ciexport const filter = (pattern, options = {}) => (p) => minimatch(p, pattern, options); 941cb0ef41Sopenharmony_ciminimatch.filter = filter; 951cb0ef41Sopenharmony_ciconst ext = (a, b = {}) => Object.assign({}, a, b); 961cb0ef41Sopenharmony_ciexport const defaults = (def) => { 971cb0ef41Sopenharmony_ci if (!def || typeof def !== 'object' || !Object.keys(def).length) { 981cb0ef41Sopenharmony_ci return minimatch; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci const orig = minimatch; 1011cb0ef41Sopenharmony_ci const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options)); 1021cb0ef41Sopenharmony_ci return Object.assign(m, { 1031cb0ef41Sopenharmony_ci Minimatch: class Minimatch extends orig.Minimatch { 1041cb0ef41Sopenharmony_ci constructor(pattern, options = {}) { 1051cb0ef41Sopenharmony_ci super(pattern, ext(def, options)); 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci static defaults(options) { 1081cb0ef41Sopenharmony_ci return orig.defaults(ext(def, options)).Minimatch; 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci }, 1111cb0ef41Sopenharmony_ci AST: class AST extends orig.AST { 1121cb0ef41Sopenharmony_ci /* c8 ignore start */ 1131cb0ef41Sopenharmony_ci constructor(type, parent, options = {}) { 1141cb0ef41Sopenharmony_ci super(type, parent, ext(def, options)); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci /* c8 ignore stop */ 1171cb0ef41Sopenharmony_ci static fromGlob(pattern, options = {}) { 1181cb0ef41Sopenharmony_ci return orig.AST.fromGlob(pattern, ext(def, options)); 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci }, 1211cb0ef41Sopenharmony_ci unescape: (s, options = {}) => orig.unescape(s, ext(def, options)), 1221cb0ef41Sopenharmony_ci escape: (s, options = {}) => orig.escape(s, ext(def, options)), 1231cb0ef41Sopenharmony_ci filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)), 1241cb0ef41Sopenharmony_ci defaults: (options) => orig.defaults(ext(def, options)), 1251cb0ef41Sopenharmony_ci makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)), 1261cb0ef41Sopenharmony_ci braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)), 1271cb0ef41Sopenharmony_ci match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)), 1281cb0ef41Sopenharmony_ci sep: orig.sep, 1291cb0ef41Sopenharmony_ci GLOBSTAR: GLOBSTAR, 1301cb0ef41Sopenharmony_ci }); 1311cb0ef41Sopenharmony_ci}; 1321cb0ef41Sopenharmony_ciminimatch.defaults = defaults; 1331cb0ef41Sopenharmony_ci// Brace expansion: 1341cb0ef41Sopenharmony_ci// a{b,c}d -> abd acd 1351cb0ef41Sopenharmony_ci// a{b,}c -> abc ac 1361cb0ef41Sopenharmony_ci// a{0..3}d -> a0d a1d a2d a3d 1371cb0ef41Sopenharmony_ci// a{b,c{d,e}f}g -> abg acdfg acefg 1381cb0ef41Sopenharmony_ci// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg 1391cb0ef41Sopenharmony_ci// 1401cb0ef41Sopenharmony_ci// Invalid sets are not expanded. 1411cb0ef41Sopenharmony_ci// a{2..}b -> a{2..}b 1421cb0ef41Sopenharmony_ci// a{b}c -> a{b}c 1431cb0ef41Sopenharmony_ciexport const braceExpand = (pattern, options = {}) => { 1441cb0ef41Sopenharmony_ci assertValidPattern(pattern); 1451cb0ef41Sopenharmony_ci // Thanks to Yeting Li <https://github.com/yetingli> for 1461cb0ef41Sopenharmony_ci // improving this regexp to avoid a ReDOS vulnerability. 1471cb0ef41Sopenharmony_ci if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) { 1481cb0ef41Sopenharmony_ci // shortcut. no need to expand. 1491cb0ef41Sopenharmony_ci return [pattern]; 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci return expand(pattern); 1521cb0ef41Sopenharmony_ci}; 1531cb0ef41Sopenharmony_ciminimatch.braceExpand = braceExpand; 1541cb0ef41Sopenharmony_ci// parse a component of the expanded set. 1551cb0ef41Sopenharmony_ci// At this point, no pattern may contain "/" in it 1561cb0ef41Sopenharmony_ci// so we're going to return a 2d array, where each entry is the full 1571cb0ef41Sopenharmony_ci// pattern, split on '/', and then turned into a regular expression. 1581cb0ef41Sopenharmony_ci// A regexp is made at the end which joins each array with an 1591cb0ef41Sopenharmony_ci// escaped /, and another full one which joins each regexp with |. 1601cb0ef41Sopenharmony_ci// 1611cb0ef41Sopenharmony_ci// Following the lead of Bash 4.1, note that "**" only has special meaning 1621cb0ef41Sopenharmony_ci// when it is the *only* thing in a path portion. Otherwise, any series 1631cb0ef41Sopenharmony_ci// of * is equivalent to a single *. Globstar behavior is enabled by 1641cb0ef41Sopenharmony_ci// default, and can be disabled by setting options.noglobstar. 1651cb0ef41Sopenharmony_ciexport const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe(); 1661cb0ef41Sopenharmony_ciminimatch.makeRe = makeRe; 1671cb0ef41Sopenharmony_ciexport const match = (list, pattern, options = {}) => { 1681cb0ef41Sopenharmony_ci const mm = new Minimatch(pattern, options); 1691cb0ef41Sopenharmony_ci list = list.filter(f => mm.match(f)); 1701cb0ef41Sopenharmony_ci if (mm.options.nonull && !list.length) { 1711cb0ef41Sopenharmony_ci list.push(pattern); 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci return list; 1741cb0ef41Sopenharmony_ci}; 1751cb0ef41Sopenharmony_ciminimatch.match = match; 1761cb0ef41Sopenharmony_ci// replace stuff like \* with * 1771cb0ef41Sopenharmony_ciconst globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/; 1781cb0ef41Sopenharmony_ciconst regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); 1791cb0ef41Sopenharmony_ciexport class Minimatch { 1801cb0ef41Sopenharmony_ci options; 1811cb0ef41Sopenharmony_ci set; 1821cb0ef41Sopenharmony_ci pattern; 1831cb0ef41Sopenharmony_ci windowsPathsNoEscape; 1841cb0ef41Sopenharmony_ci nonegate; 1851cb0ef41Sopenharmony_ci negate; 1861cb0ef41Sopenharmony_ci comment; 1871cb0ef41Sopenharmony_ci empty; 1881cb0ef41Sopenharmony_ci preserveMultipleSlashes; 1891cb0ef41Sopenharmony_ci partial; 1901cb0ef41Sopenharmony_ci globSet; 1911cb0ef41Sopenharmony_ci globParts; 1921cb0ef41Sopenharmony_ci nocase; 1931cb0ef41Sopenharmony_ci isWindows; 1941cb0ef41Sopenharmony_ci platform; 1951cb0ef41Sopenharmony_ci windowsNoMagicRoot; 1961cb0ef41Sopenharmony_ci regexp; 1971cb0ef41Sopenharmony_ci constructor(pattern, options = {}) { 1981cb0ef41Sopenharmony_ci assertValidPattern(pattern); 1991cb0ef41Sopenharmony_ci options = options || {}; 2001cb0ef41Sopenharmony_ci this.options = options; 2011cb0ef41Sopenharmony_ci this.pattern = pattern; 2021cb0ef41Sopenharmony_ci this.platform = options.platform || defaultPlatform; 2031cb0ef41Sopenharmony_ci this.isWindows = this.platform === 'win32'; 2041cb0ef41Sopenharmony_ci this.windowsPathsNoEscape = 2051cb0ef41Sopenharmony_ci !!options.windowsPathsNoEscape || options.allowWindowsEscape === false; 2061cb0ef41Sopenharmony_ci if (this.windowsPathsNoEscape) { 2071cb0ef41Sopenharmony_ci this.pattern = this.pattern.replace(/\\/g, '/'); 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci this.preserveMultipleSlashes = !!options.preserveMultipleSlashes; 2101cb0ef41Sopenharmony_ci this.regexp = null; 2111cb0ef41Sopenharmony_ci this.negate = false; 2121cb0ef41Sopenharmony_ci this.nonegate = !!options.nonegate; 2131cb0ef41Sopenharmony_ci this.comment = false; 2141cb0ef41Sopenharmony_ci this.empty = false; 2151cb0ef41Sopenharmony_ci this.partial = !!options.partial; 2161cb0ef41Sopenharmony_ci this.nocase = !!this.options.nocase; 2171cb0ef41Sopenharmony_ci this.windowsNoMagicRoot = 2181cb0ef41Sopenharmony_ci options.windowsNoMagicRoot !== undefined 2191cb0ef41Sopenharmony_ci ? options.windowsNoMagicRoot 2201cb0ef41Sopenharmony_ci : !!(this.isWindows && this.nocase); 2211cb0ef41Sopenharmony_ci this.globSet = []; 2221cb0ef41Sopenharmony_ci this.globParts = []; 2231cb0ef41Sopenharmony_ci this.set = []; 2241cb0ef41Sopenharmony_ci // make the set of regexps etc. 2251cb0ef41Sopenharmony_ci this.make(); 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci hasMagic() { 2281cb0ef41Sopenharmony_ci if (this.options.magicalBraces && this.set.length > 1) { 2291cb0ef41Sopenharmony_ci return true; 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci for (const pattern of this.set) { 2321cb0ef41Sopenharmony_ci for (const part of pattern) { 2331cb0ef41Sopenharmony_ci if (typeof part !== 'string') 2341cb0ef41Sopenharmony_ci return true; 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci } 2371cb0ef41Sopenharmony_ci return false; 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci debug(..._) { } 2401cb0ef41Sopenharmony_ci make() { 2411cb0ef41Sopenharmony_ci const pattern = this.pattern; 2421cb0ef41Sopenharmony_ci const options = this.options; 2431cb0ef41Sopenharmony_ci // empty patterns and comments match nothing. 2441cb0ef41Sopenharmony_ci if (!options.nocomment && pattern.charAt(0) === '#') { 2451cb0ef41Sopenharmony_ci this.comment = true; 2461cb0ef41Sopenharmony_ci return; 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci if (!pattern) { 2491cb0ef41Sopenharmony_ci this.empty = true; 2501cb0ef41Sopenharmony_ci return; 2511cb0ef41Sopenharmony_ci } 2521cb0ef41Sopenharmony_ci // step 1: figure out negation, etc. 2531cb0ef41Sopenharmony_ci this.parseNegate(); 2541cb0ef41Sopenharmony_ci // step 2: expand braces 2551cb0ef41Sopenharmony_ci this.globSet = [...new Set(this.braceExpand())]; 2561cb0ef41Sopenharmony_ci if (options.debug) { 2571cb0ef41Sopenharmony_ci this.debug = (...args) => console.error(...args); 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci this.debug(this.pattern, this.globSet); 2601cb0ef41Sopenharmony_ci // step 3: now we have a set, so turn each one into a series of 2611cb0ef41Sopenharmony_ci // path-portion matching patterns. 2621cb0ef41Sopenharmony_ci // These will be regexps, except in the case of "**", which is 2631cb0ef41Sopenharmony_ci // set to the GLOBSTAR object for globstar behavior, 2641cb0ef41Sopenharmony_ci // and will not contain any / characters 2651cb0ef41Sopenharmony_ci // 2661cb0ef41Sopenharmony_ci // First, we preprocess to make the glob pattern sets a bit simpler 2671cb0ef41Sopenharmony_ci // and deduped. There are some perf-killing patterns that can cause 2681cb0ef41Sopenharmony_ci // problems with a glob walk, but we can simplify them down a bit. 2691cb0ef41Sopenharmony_ci const rawGlobParts = this.globSet.map(s => this.slashSplit(s)); 2701cb0ef41Sopenharmony_ci this.globParts = this.preprocess(rawGlobParts); 2711cb0ef41Sopenharmony_ci this.debug(this.pattern, this.globParts); 2721cb0ef41Sopenharmony_ci // glob --> regexps 2731cb0ef41Sopenharmony_ci let set = this.globParts.map((s, _, __) => { 2741cb0ef41Sopenharmony_ci if (this.isWindows && this.windowsNoMagicRoot) { 2751cb0ef41Sopenharmony_ci // check if it's a drive or unc path. 2761cb0ef41Sopenharmony_ci const isUNC = s[0] === '' && 2771cb0ef41Sopenharmony_ci s[1] === '' && 2781cb0ef41Sopenharmony_ci (s[2] === '?' || !globMagic.test(s[2])) && 2791cb0ef41Sopenharmony_ci !globMagic.test(s[3]); 2801cb0ef41Sopenharmony_ci const isDrive = /^[a-z]:/i.test(s[0]); 2811cb0ef41Sopenharmony_ci if (isUNC) { 2821cb0ef41Sopenharmony_ci return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))]; 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci else if (isDrive) { 2851cb0ef41Sopenharmony_ci return [s[0], ...s.slice(1).map(ss => this.parse(ss))]; 2861cb0ef41Sopenharmony_ci } 2871cb0ef41Sopenharmony_ci } 2881cb0ef41Sopenharmony_ci return s.map(ss => this.parse(ss)); 2891cb0ef41Sopenharmony_ci }); 2901cb0ef41Sopenharmony_ci this.debug(this.pattern, set); 2911cb0ef41Sopenharmony_ci // filter out everything that didn't compile properly. 2921cb0ef41Sopenharmony_ci this.set = set.filter(s => s.indexOf(false) === -1); 2931cb0ef41Sopenharmony_ci // do not treat the ? in UNC paths as magic 2941cb0ef41Sopenharmony_ci if (this.isWindows) { 2951cb0ef41Sopenharmony_ci for (let i = 0; i < this.set.length; i++) { 2961cb0ef41Sopenharmony_ci const p = this.set[i]; 2971cb0ef41Sopenharmony_ci if (p[0] === '' && 2981cb0ef41Sopenharmony_ci p[1] === '' && 2991cb0ef41Sopenharmony_ci this.globParts[i][2] === '?' && 3001cb0ef41Sopenharmony_ci typeof p[3] === 'string' && 3011cb0ef41Sopenharmony_ci /^[a-z]:$/i.test(p[3])) { 3021cb0ef41Sopenharmony_ci p[2] = '?'; 3031cb0ef41Sopenharmony_ci } 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci } 3061cb0ef41Sopenharmony_ci this.debug(this.pattern, this.set); 3071cb0ef41Sopenharmony_ci } 3081cb0ef41Sopenharmony_ci // various transforms to equivalent pattern sets that are 3091cb0ef41Sopenharmony_ci // faster to process in a filesystem walk. The goal is to 3101cb0ef41Sopenharmony_ci // eliminate what we can, and push all ** patterns as far 3111cb0ef41Sopenharmony_ci // to the right as possible, even if it increases the number 3121cb0ef41Sopenharmony_ci // of patterns that we have to process. 3131cb0ef41Sopenharmony_ci preprocess(globParts) { 3141cb0ef41Sopenharmony_ci // if we're not in globstar mode, then turn all ** into * 3151cb0ef41Sopenharmony_ci if (this.options.noglobstar) { 3161cb0ef41Sopenharmony_ci for (let i = 0; i < globParts.length; i++) { 3171cb0ef41Sopenharmony_ci for (let j = 0; j < globParts[i].length; j++) { 3181cb0ef41Sopenharmony_ci if (globParts[i][j] === '**') { 3191cb0ef41Sopenharmony_ci globParts[i][j] = '*'; 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci } 3221cb0ef41Sopenharmony_ci } 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci const { optimizationLevel = 1 } = this.options; 3251cb0ef41Sopenharmony_ci if (optimizationLevel >= 2) { 3261cb0ef41Sopenharmony_ci // aggressive optimization for the purpose of fs walking 3271cb0ef41Sopenharmony_ci globParts = this.firstPhasePreProcess(globParts); 3281cb0ef41Sopenharmony_ci globParts = this.secondPhasePreProcess(globParts); 3291cb0ef41Sopenharmony_ci } 3301cb0ef41Sopenharmony_ci else if (optimizationLevel >= 1) { 3311cb0ef41Sopenharmony_ci // just basic optimizations to remove some .. parts 3321cb0ef41Sopenharmony_ci globParts = this.levelOneOptimize(globParts); 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci else { 3351cb0ef41Sopenharmony_ci globParts = this.adjascentGlobstarOptimize(globParts); 3361cb0ef41Sopenharmony_ci } 3371cb0ef41Sopenharmony_ci return globParts; 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci // just get rid of adjascent ** portions 3401cb0ef41Sopenharmony_ci adjascentGlobstarOptimize(globParts) { 3411cb0ef41Sopenharmony_ci return globParts.map(parts => { 3421cb0ef41Sopenharmony_ci let gs = -1; 3431cb0ef41Sopenharmony_ci while (-1 !== (gs = parts.indexOf('**', gs + 1))) { 3441cb0ef41Sopenharmony_ci let i = gs; 3451cb0ef41Sopenharmony_ci while (parts[i + 1] === '**') { 3461cb0ef41Sopenharmony_ci i++; 3471cb0ef41Sopenharmony_ci } 3481cb0ef41Sopenharmony_ci if (i !== gs) { 3491cb0ef41Sopenharmony_ci parts.splice(gs, i - gs); 3501cb0ef41Sopenharmony_ci } 3511cb0ef41Sopenharmony_ci } 3521cb0ef41Sopenharmony_ci return parts; 3531cb0ef41Sopenharmony_ci }); 3541cb0ef41Sopenharmony_ci } 3551cb0ef41Sopenharmony_ci // get rid of adjascent ** and resolve .. portions 3561cb0ef41Sopenharmony_ci levelOneOptimize(globParts) { 3571cb0ef41Sopenharmony_ci return globParts.map(parts => { 3581cb0ef41Sopenharmony_ci parts = parts.reduce((set, part) => { 3591cb0ef41Sopenharmony_ci const prev = set[set.length - 1]; 3601cb0ef41Sopenharmony_ci if (part === '**' && prev === '**') { 3611cb0ef41Sopenharmony_ci return set; 3621cb0ef41Sopenharmony_ci } 3631cb0ef41Sopenharmony_ci if (part === '..') { 3641cb0ef41Sopenharmony_ci if (prev && prev !== '..' && prev !== '.' && prev !== '**') { 3651cb0ef41Sopenharmony_ci set.pop(); 3661cb0ef41Sopenharmony_ci return set; 3671cb0ef41Sopenharmony_ci } 3681cb0ef41Sopenharmony_ci } 3691cb0ef41Sopenharmony_ci set.push(part); 3701cb0ef41Sopenharmony_ci return set; 3711cb0ef41Sopenharmony_ci }, []); 3721cb0ef41Sopenharmony_ci return parts.length === 0 ? [''] : parts; 3731cb0ef41Sopenharmony_ci }); 3741cb0ef41Sopenharmony_ci } 3751cb0ef41Sopenharmony_ci levelTwoFileOptimize(parts) { 3761cb0ef41Sopenharmony_ci if (!Array.isArray(parts)) { 3771cb0ef41Sopenharmony_ci parts = this.slashSplit(parts); 3781cb0ef41Sopenharmony_ci } 3791cb0ef41Sopenharmony_ci let didSomething = false; 3801cb0ef41Sopenharmony_ci do { 3811cb0ef41Sopenharmony_ci didSomething = false; 3821cb0ef41Sopenharmony_ci // <pre>/<e>/<rest> -> <pre>/<rest> 3831cb0ef41Sopenharmony_ci if (!this.preserveMultipleSlashes) { 3841cb0ef41Sopenharmony_ci for (let i = 1; i < parts.length - 1; i++) { 3851cb0ef41Sopenharmony_ci const p = parts[i]; 3861cb0ef41Sopenharmony_ci // don't squeeze out UNC patterns 3871cb0ef41Sopenharmony_ci if (i === 1 && p === '' && parts[0] === '') 3881cb0ef41Sopenharmony_ci continue; 3891cb0ef41Sopenharmony_ci if (p === '.' || p === '') { 3901cb0ef41Sopenharmony_ci didSomething = true; 3911cb0ef41Sopenharmony_ci parts.splice(i, 1); 3921cb0ef41Sopenharmony_ci i--; 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci if (parts[0] === '.' && 3961cb0ef41Sopenharmony_ci parts.length === 2 && 3971cb0ef41Sopenharmony_ci (parts[1] === '.' || parts[1] === '')) { 3981cb0ef41Sopenharmony_ci didSomething = true; 3991cb0ef41Sopenharmony_ci parts.pop(); 4001cb0ef41Sopenharmony_ci } 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci // <pre>/<p>/../<rest> -> <pre>/<rest> 4031cb0ef41Sopenharmony_ci let dd = 0; 4041cb0ef41Sopenharmony_ci while (-1 !== (dd = parts.indexOf('..', dd + 1))) { 4051cb0ef41Sopenharmony_ci const p = parts[dd - 1]; 4061cb0ef41Sopenharmony_ci if (p && p !== '.' && p !== '..' && p !== '**') { 4071cb0ef41Sopenharmony_ci didSomething = true; 4081cb0ef41Sopenharmony_ci parts.splice(dd - 1, 2); 4091cb0ef41Sopenharmony_ci dd -= 2; 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci } 4121cb0ef41Sopenharmony_ci } while (didSomething); 4131cb0ef41Sopenharmony_ci return parts.length === 0 ? [''] : parts; 4141cb0ef41Sopenharmony_ci } 4151cb0ef41Sopenharmony_ci // First phase: single-pattern processing 4161cb0ef41Sopenharmony_ci // <pre> is 1 or more portions 4171cb0ef41Sopenharmony_ci // <rest> is 1 or more portions 4181cb0ef41Sopenharmony_ci // <p> is any portion other than ., .., '', or ** 4191cb0ef41Sopenharmony_ci // <e> is . or '' 4201cb0ef41Sopenharmony_ci // 4211cb0ef41Sopenharmony_ci // **/.. is *brutal* for filesystem walking performance, because 4221cb0ef41Sopenharmony_ci // it effectively resets the recursive walk each time it occurs, 4231cb0ef41Sopenharmony_ci // and ** cannot be reduced out by a .. pattern part like a regexp 4241cb0ef41Sopenharmony_ci // or most strings (other than .., ., and '') can be. 4251cb0ef41Sopenharmony_ci // 4261cb0ef41Sopenharmony_ci // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>} 4271cb0ef41Sopenharmony_ci // <pre>/<e>/<rest> -> <pre>/<rest> 4281cb0ef41Sopenharmony_ci // <pre>/<p>/../<rest> -> <pre>/<rest> 4291cb0ef41Sopenharmony_ci // **/**/<rest> -> **/<rest> 4301cb0ef41Sopenharmony_ci // 4311cb0ef41Sopenharmony_ci // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow 4321cb0ef41Sopenharmony_ci // this WOULD be allowed if ** did follow symlinks, or * didn't 4331cb0ef41Sopenharmony_ci firstPhasePreProcess(globParts) { 4341cb0ef41Sopenharmony_ci let didSomething = false; 4351cb0ef41Sopenharmony_ci do { 4361cb0ef41Sopenharmony_ci didSomething = false; 4371cb0ef41Sopenharmony_ci // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>} 4381cb0ef41Sopenharmony_ci for (let parts of globParts) { 4391cb0ef41Sopenharmony_ci let gs = -1; 4401cb0ef41Sopenharmony_ci while (-1 !== (gs = parts.indexOf('**', gs + 1))) { 4411cb0ef41Sopenharmony_ci let gss = gs; 4421cb0ef41Sopenharmony_ci while (parts[gss + 1] === '**') { 4431cb0ef41Sopenharmony_ci // <pre>/**/**/<rest> -> <pre>/**/<rest> 4441cb0ef41Sopenharmony_ci gss++; 4451cb0ef41Sopenharmony_ci } 4461cb0ef41Sopenharmony_ci // eg, if gs is 2 and gss is 4, that means we have 3 ** 4471cb0ef41Sopenharmony_ci // parts, and can remove 2 of them. 4481cb0ef41Sopenharmony_ci if (gss > gs) { 4491cb0ef41Sopenharmony_ci parts.splice(gs + 1, gss - gs); 4501cb0ef41Sopenharmony_ci } 4511cb0ef41Sopenharmony_ci let next = parts[gs + 1]; 4521cb0ef41Sopenharmony_ci const p = parts[gs + 2]; 4531cb0ef41Sopenharmony_ci const p2 = parts[gs + 3]; 4541cb0ef41Sopenharmony_ci if (next !== '..') 4551cb0ef41Sopenharmony_ci continue; 4561cb0ef41Sopenharmony_ci if (!p || 4571cb0ef41Sopenharmony_ci p === '.' || 4581cb0ef41Sopenharmony_ci p === '..' || 4591cb0ef41Sopenharmony_ci !p2 || 4601cb0ef41Sopenharmony_ci p2 === '.' || 4611cb0ef41Sopenharmony_ci p2 === '..') { 4621cb0ef41Sopenharmony_ci continue; 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci didSomething = true; 4651cb0ef41Sopenharmony_ci // edit parts in place, and push the new one 4661cb0ef41Sopenharmony_ci parts.splice(gs, 1); 4671cb0ef41Sopenharmony_ci const other = parts.slice(0); 4681cb0ef41Sopenharmony_ci other[gs] = '**'; 4691cb0ef41Sopenharmony_ci globParts.push(other); 4701cb0ef41Sopenharmony_ci gs--; 4711cb0ef41Sopenharmony_ci } 4721cb0ef41Sopenharmony_ci // <pre>/<e>/<rest> -> <pre>/<rest> 4731cb0ef41Sopenharmony_ci if (!this.preserveMultipleSlashes) { 4741cb0ef41Sopenharmony_ci for (let i = 1; i < parts.length - 1; i++) { 4751cb0ef41Sopenharmony_ci const p = parts[i]; 4761cb0ef41Sopenharmony_ci // don't squeeze out UNC patterns 4771cb0ef41Sopenharmony_ci if (i === 1 && p === '' && parts[0] === '') 4781cb0ef41Sopenharmony_ci continue; 4791cb0ef41Sopenharmony_ci if (p === '.' || p === '') { 4801cb0ef41Sopenharmony_ci didSomething = true; 4811cb0ef41Sopenharmony_ci parts.splice(i, 1); 4821cb0ef41Sopenharmony_ci i--; 4831cb0ef41Sopenharmony_ci } 4841cb0ef41Sopenharmony_ci } 4851cb0ef41Sopenharmony_ci if (parts[0] === '.' && 4861cb0ef41Sopenharmony_ci parts.length === 2 && 4871cb0ef41Sopenharmony_ci (parts[1] === '.' || parts[1] === '')) { 4881cb0ef41Sopenharmony_ci didSomething = true; 4891cb0ef41Sopenharmony_ci parts.pop(); 4901cb0ef41Sopenharmony_ci } 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci // <pre>/<p>/../<rest> -> <pre>/<rest> 4931cb0ef41Sopenharmony_ci let dd = 0; 4941cb0ef41Sopenharmony_ci while (-1 !== (dd = parts.indexOf('..', dd + 1))) { 4951cb0ef41Sopenharmony_ci const p = parts[dd - 1]; 4961cb0ef41Sopenharmony_ci if (p && p !== '.' && p !== '..' && p !== '**') { 4971cb0ef41Sopenharmony_ci didSomething = true; 4981cb0ef41Sopenharmony_ci const needDot = dd === 1 && parts[dd + 1] === '**'; 4991cb0ef41Sopenharmony_ci const splin = needDot ? ['.'] : []; 5001cb0ef41Sopenharmony_ci parts.splice(dd - 1, 2, ...splin); 5011cb0ef41Sopenharmony_ci if (parts.length === 0) 5021cb0ef41Sopenharmony_ci parts.push(''); 5031cb0ef41Sopenharmony_ci dd -= 2; 5041cb0ef41Sopenharmony_ci } 5051cb0ef41Sopenharmony_ci } 5061cb0ef41Sopenharmony_ci } 5071cb0ef41Sopenharmony_ci } while (didSomething); 5081cb0ef41Sopenharmony_ci return globParts; 5091cb0ef41Sopenharmony_ci } 5101cb0ef41Sopenharmony_ci // second phase: multi-pattern dedupes 5111cb0ef41Sopenharmony_ci // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest> 5121cb0ef41Sopenharmony_ci // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest> 5131cb0ef41Sopenharmony_ci // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest> 5141cb0ef41Sopenharmony_ci // 5151cb0ef41Sopenharmony_ci // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest> 5161cb0ef41Sopenharmony_ci // ^-- not valid because ** doens't follow symlinks 5171cb0ef41Sopenharmony_ci secondPhasePreProcess(globParts) { 5181cb0ef41Sopenharmony_ci for (let i = 0; i < globParts.length - 1; i++) { 5191cb0ef41Sopenharmony_ci for (let j = i + 1; j < globParts.length; j++) { 5201cb0ef41Sopenharmony_ci const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes); 5211cb0ef41Sopenharmony_ci if (!matched) 5221cb0ef41Sopenharmony_ci continue; 5231cb0ef41Sopenharmony_ci globParts[i] = matched; 5241cb0ef41Sopenharmony_ci globParts[j] = []; 5251cb0ef41Sopenharmony_ci } 5261cb0ef41Sopenharmony_ci } 5271cb0ef41Sopenharmony_ci return globParts.filter(gs => gs.length); 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci partsMatch(a, b, emptyGSMatch = false) { 5301cb0ef41Sopenharmony_ci let ai = 0; 5311cb0ef41Sopenharmony_ci let bi = 0; 5321cb0ef41Sopenharmony_ci let result = []; 5331cb0ef41Sopenharmony_ci let which = ''; 5341cb0ef41Sopenharmony_ci while (ai < a.length && bi < b.length) { 5351cb0ef41Sopenharmony_ci if (a[ai] === b[bi]) { 5361cb0ef41Sopenharmony_ci result.push(which === 'b' ? b[bi] : a[ai]); 5371cb0ef41Sopenharmony_ci ai++; 5381cb0ef41Sopenharmony_ci bi++; 5391cb0ef41Sopenharmony_ci } 5401cb0ef41Sopenharmony_ci else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) { 5411cb0ef41Sopenharmony_ci result.push(a[ai]); 5421cb0ef41Sopenharmony_ci ai++; 5431cb0ef41Sopenharmony_ci } 5441cb0ef41Sopenharmony_ci else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) { 5451cb0ef41Sopenharmony_ci result.push(b[bi]); 5461cb0ef41Sopenharmony_ci bi++; 5471cb0ef41Sopenharmony_ci } 5481cb0ef41Sopenharmony_ci else if (a[ai] === '*' && 5491cb0ef41Sopenharmony_ci b[bi] && 5501cb0ef41Sopenharmony_ci (this.options.dot || !b[bi].startsWith('.')) && 5511cb0ef41Sopenharmony_ci b[bi] !== '**') { 5521cb0ef41Sopenharmony_ci if (which === 'b') 5531cb0ef41Sopenharmony_ci return false; 5541cb0ef41Sopenharmony_ci which = 'a'; 5551cb0ef41Sopenharmony_ci result.push(a[ai]); 5561cb0ef41Sopenharmony_ci ai++; 5571cb0ef41Sopenharmony_ci bi++; 5581cb0ef41Sopenharmony_ci } 5591cb0ef41Sopenharmony_ci else if (b[bi] === '*' && 5601cb0ef41Sopenharmony_ci a[ai] && 5611cb0ef41Sopenharmony_ci (this.options.dot || !a[ai].startsWith('.')) && 5621cb0ef41Sopenharmony_ci a[ai] !== '**') { 5631cb0ef41Sopenharmony_ci if (which === 'a') 5641cb0ef41Sopenharmony_ci return false; 5651cb0ef41Sopenharmony_ci which = 'b'; 5661cb0ef41Sopenharmony_ci result.push(b[bi]); 5671cb0ef41Sopenharmony_ci ai++; 5681cb0ef41Sopenharmony_ci bi++; 5691cb0ef41Sopenharmony_ci } 5701cb0ef41Sopenharmony_ci else { 5711cb0ef41Sopenharmony_ci return false; 5721cb0ef41Sopenharmony_ci } 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci // if we fall out of the loop, it means they two are identical 5751cb0ef41Sopenharmony_ci // as long as their lengths match 5761cb0ef41Sopenharmony_ci return a.length === b.length && result; 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci parseNegate() { 5791cb0ef41Sopenharmony_ci if (this.nonegate) 5801cb0ef41Sopenharmony_ci return; 5811cb0ef41Sopenharmony_ci const pattern = this.pattern; 5821cb0ef41Sopenharmony_ci let negate = false; 5831cb0ef41Sopenharmony_ci let negateOffset = 0; 5841cb0ef41Sopenharmony_ci for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) { 5851cb0ef41Sopenharmony_ci negate = !negate; 5861cb0ef41Sopenharmony_ci negateOffset++; 5871cb0ef41Sopenharmony_ci } 5881cb0ef41Sopenharmony_ci if (negateOffset) 5891cb0ef41Sopenharmony_ci this.pattern = pattern.slice(negateOffset); 5901cb0ef41Sopenharmony_ci this.negate = negate; 5911cb0ef41Sopenharmony_ci } 5921cb0ef41Sopenharmony_ci // set partial to true to test if, for example, 5931cb0ef41Sopenharmony_ci // "/a/b" matches the start of "/*/b/*/d" 5941cb0ef41Sopenharmony_ci // Partial means, if you run out of file before you run 5951cb0ef41Sopenharmony_ci // out of pattern, then that's fine, as long as all 5961cb0ef41Sopenharmony_ci // the parts match. 5971cb0ef41Sopenharmony_ci matchOne(file, pattern, partial = false) { 5981cb0ef41Sopenharmony_ci const options = this.options; 5991cb0ef41Sopenharmony_ci // UNC paths like //?/X:/... can match X:/... and vice versa 6001cb0ef41Sopenharmony_ci // Drive letters in absolute drive or unc paths are always compared 6011cb0ef41Sopenharmony_ci // case-insensitively. 6021cb0ef41Sopenharmony_ci if (this.isWindows) { 6031cb0ef41Sopenharmony_ci const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]); 6041cb0ef41Sopenharmony_ci const fileUNC = !fileDrive && 6051cb0ef41Sopenharmony_ci file[0] === '' && 6061cb0ef41Sopenharmony_ci file[1] === '' && 6071cb0ef41Sopenharmony_ci file[2] === '?' && 6081cb0ef41Sopenharmony_ci /^[a-z]:$/i.test(file[3]); 6091cb0ef41Sopenharmony_ci const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]); 6101cb0ef41Sopenharmony_ci const patternUNC = !patternDrive && 6111cb0ef41Sopenharmony_ci pattern[0] === '' && 6121cb0ef41Sopenharmony_ci pattern[1] === '' && 6131cb0ef41Sopenharmony_ci pattern[2] === '?' && 6141cb0ef41Sopenharmony_ci typeof pattern[3] === 'string' && 6151cb0ef41Sopenharmony_ci /^[a-z]:$/i.test(pattern[3]); 6161cb0ef41Sopenharmony_ci const fdi = fileUNC ? 3 : fileDrive ? 0 : undefined; 6171cb0ef41Sopenharmony_ci const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined; 6181cb0ef41Sopenharmony_ci if (typeof fdi === 'number' && typeof pdi === 'number') { 6191cb0ef41Sopenharmony_ci const [fd, pd] = [file[fdi], pattern[pdi]]; 6201cb0ef41Sopenharmony_ci if (fd.toLowerCase() === pd.toLowerCase()) { 6211cb0ef41Sopenharmony_ci pattern[pdi] = fd; 6221cb0ef41Sopenharmony_ci if (pdi > fdi) { 6231cb0ef41Sopenharmony_ci pattern = pattern.slice(pdi); 6241cb0ef41Sopenharmony_ci } 6251cb0ef41Sopenharmony_ci else if (fdi > pdi) { 6261cb0ef41Sopenharmony_ci file = file.slice(fdi); 6271cb0ef41Sopenharmony_ci } 6281cb0ef41Sopenharmony_ci } 6291cb0ef41Sopenharmony_ci } 6301cb0ef41Sopenharmony_ci } 6311cb0ef41Sopenharmony_ci // resolve and reduce . and .. portions in the file as well. 6321cb0ef41Sopenharmony_ci // dont' need to do the second phase, because it's only one string[] 6331cb0ef41Sopenharmony_ci const { optimizationLevel = 1 } = this.options; 6341cb0ef41Sopenharmony_ci if (optimizationLevel >= 2) { 6351cb0ef41Sopenharmony_ci file = this.levelTwoFileOptimize(file); 6361cb0ef41Sopenharmony_ci } 6371cb0ef41Sopenharmony_ci this.debug('matchOne', this, { file, pattern }); 6381cb0ef41Sopenharmony_ci this.debug('matchOne', file.length, pattern.length); 6391cb0ef41Sopenharmony_ci for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) { 6401cb0ef41Sopenharmony_ci this.debug('matchOne loop'); 6411cb0ef41Sopenharmony_ci var p = pattern[pi]; 6421cb0ef41Sopenharmony_ci var f = file[fi]; 6431cb0ef41Sopenharmony_ci this.debug(pattern, p, f); 6441cb0ef41Sopenharmony_ci // should be impossible. 6451cb0ef41Sopenharmony_ci // some invalid regexp stuff in the set. 6461cb0ef41Sopenharmony_ci /* c8 ignore start */ 6471cb0ef41Sopenharmony_ci if (p === false) { 6481cb0ef41Sopenharmony_ci return false; 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci /* c8 ignore stop */ 6511cb0ef41Sopenharmony_ci if (p === GLOBSTAR) { 6521cb0ef41Sopenharmony_ci this.debug('GLOBSTAR', [pattern, p, f]); 6531cb0ef41Sopenharmony_ci // "**" 6541cb0ef41Sopenharmony_ci // a/**/b/**/c would match the following: 6551cb0ef41Sopenharmony_ci // a/b/x/y/z/c 6561cb0ef41Sopenharmony_ci // a/x/y/z/b/c 6571cb0ef41Sopenharmony_ci // a/b/x/b/x/c 6581cb0ef41Sopenharmony_ci // a/b/c 6591cb0ef41Sopenharmony_ci // To do this, take the rest of the pattern after 6601cb0ef41Sopenharmony_ci // the **, and see if it would match the file remainder. 6611cb0ef41Sopenharmony_ci // If so, return success. 6621cb0ef41Sopenharmony_ci // If not, the ** "swallows" a segment, and try again. 6631cb0ef41Sopenharmony_ci // This is recursively awful. 6641cb0ef41Sopenharmony_ci // 6651cb0ef41Sopenharmony_ci // a/**/b/**/c matching a/b/x/y/z/c 6661cb0ef41Sopenharmony_ci // - a matches a 6671cb0ef41Sopenharmony_ci // - doublestar 6681cb0ef41Sopenharmony_ci // - matchOne(b/x/y/z/c, b/**/c) 6691cb0ef41Sopenharmony_ci // - b matches b 6701cb0ef41Sopenharmony_ci // - doublestar 6711cb0ef41Sopenharmony_ci // - matchOne(x/y/z/c, c) -> no 6721cb0ef41Sopenharmony_ci // - matchOne(y/z/c, c) -> no 6731cb0ef41Sopenharmony_ci // - matchOne(z/c, c) -> no 6741cb0ef41Sopenharmony_ci // - matchOne(c, c) yes, hit 6751cb0ef41Sopenharmony_ci var fr = fi; 6761cb0ef41Sopenharmony_ci var pr = pi + 1; 6771cb0ef41Sopenharmony_ci if (pr === pl) { 6781cb0ef41Sopenharmony_ci this.debug('** at the end'); 6791cb0ef41Sopenharmony_ci // a ** at the end will just swallow the rest. 6801cb0ef41Sopenharmony_ci // We have found a match. 6811cb0ef41Sopenharmony_ci // however, it will not swallow /.x, unless 6821cb0ef41Sopenharmony_ci // options.dot is set. 6831cb0ef41Sopenharmony_ci // . and .. are *never* matched by **, for explosively 6841cb0ef41Sopenharmony_ci // exponential reasons. 6851cb0ef41Sopenharmony_ci for (; fi < fl; fi++) { 6861cb0ef41Sopenharmony_ci if (file[fi] === '.' || 6871cb0ef41Sopenharmony_ci file[fi] === '..' || 6881cb0ef41Sopenharmony_ci (!options.dot && file[fi].charAt(0) === '.')) 6891cb0ef41Sopenharmony_ci return false; 6901cb0ef41Sopenharmony_ci } 6911cb0ef41Sopenharmony_ci return true; 6921cb0ef41Sopenharmony_ci } 6931cb0ef41Sopenharmony_ci // ok, let's see if we can swallow whatever we can. 6941cb0ef41Sopenharmony_ci while (fr < fl) { 6951cb0ef41Sopenharmony_ci var swallowee = file[fr]; 6961cb0ef41Sopenharmony_ci this.debug('\nglobstar while', file, fr, pattern, pr, swallowee); 6971cb0ef41Sopenharmony_ci // XXX remove this slice. Just pass the start index. 6981cb0ef41Sopenharmony_ci if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { 6991cb0ef41Sopenharmony_ci this.debug('globstar found match!', fr, fl, swallowee); 7001cb0ef41Sopenharmony_ci // found a match. 7011cb0ef41Sopenharmony_ci return true; 7021cb0ef41Sopenharmony_ci } 7031cb0ef41Sopenharmony_ci else { 7041cb0ef41Sopenharmony_ci // can't swallow "." or ".." ever. 7051cb0ef41Sopenharmony_ci // can only swallow ".foo" when explicitly asked. 7061cb0ef41Sopenharmony_ci if (swallowee === '.' || 7071cb0ef41Sopenharmony_ci swallowee === '..' || 7081cb0ef41Sopenharmony_ci (!options.dot && swallowee.charAt(0) === '.')) { 7091cb0ef41Sopenharmony_ci this.debug('dot detected!', file, fr, pattern, pr); 7101cb0ef41Sopenharmony_ci break; 7111cb0ef41Sopenharmony_ci } 7121cb0ef41Sopenharmony_ci // ** swallows a segment, and continue. 7131cb0ef41Sopenharmony_ci this.debug('globstar swallow a segment, and continue'); 7141cb0ef41Sopenharmony_ci fr++; 7151cb0ef41Sopenharmony_ci } 7161cb0ef41Sopenharmony_ci } 7171cb0ef41Sopenharmony_ci // no match was found. 7181cb0ef41Sopenharmony_ci // However, in partial mode, we can't say this is necessarily over. 7191cb0ef41Sopenharmony_ci /* c8 ignore start */ 7201cb0ef41Sopenharmony_ci if (partial) { 7211cb0ef41Sopenharmony_ci // ran out of file 7221cb0ef41Sopenharmony_ci this.debug('\n>>> no match, partial?', file, fr, pattern, pr); 7231cb0ef41Sopenharmony_ci if (fr === fl) { 7241cb0ef41Sopenharmony_ci return true; 7251cb0ef41Sopenharmony_ci } 7261cb0ef41Sopenharmony_ci } 7271cb0ef41Sopenharmony_ci /* c8 ignore stop */ 7281cb0ef41Sopenharmony_ci return false; 7291cb0ef41Sopenharmony_ci } 7301cb0ef41Sopenharmony_ci // something other than ** 7311cb0ef41Sopenharmony_ci // non-magic patterns just have to match exactly 7321cb0ef41Sopenharmony_ci // patterns with magic have been turned into regexps. 7331cb0ef41Sopenharmony_ci let hit; 7341cb0ef41Sopenharmony_ci if (typeof p === 'string') { 7351cb0ef41Sopenharmony_ci hit = f === p; 7361cb0ef41Sopenharmony_ci this.debug('string match', p, f, hit); 7371cb0ef41Sopenharmony_ci } 7381cb0ef41Sopenharmony_ci else { 7391cb0ef41Sopenharmony_ci hit = p.test(f); 7401cb0ef41Sopenharmony_ci this.debug('pattern match', p, f, hit); 7411cb0ef41Sopenharmony_ci } 7421cb0ef41Sopenharmony_ci if (!hit) 7431cb0ef41Sopenharmony_ci return false; 7441cb0ef41Sopenharmony_ci } 7451cb0ef41Sopenharmony_ci // Note: ending in / means that we'll get a final "" 7461cb0ef41Sopenharmony_ci // at the end of the pattern. This can only match a 7471cb0ef41Sopenharmony_ci // corresponding "" at the end of the file. 7481cb0ef41Sopenharmony_ci // If the file ends in /, then it can only match a 7491cb0ef41Sopenharmony_ci // a pattern that ends in /, unless the pattern just 7501cb0ef41Sopenharmony_ci // doesn't have any more for it. But, a/b/ should *not* 7511cb0ef41Sopenharmony_ci // match "a/b/*", even though "" matches against the 7521cb0ef41Sopenharmony_ci // [^/]*? pattern, except in partial mode, where it might 7531cb0ef41Sopenharmony_ci // simply not be reached yet. 7541cb0ef41Sopenharmony_ci // However, a/b/ should still satisfy a/* 7551cb0ef41Sopenharmony_ci // now either we fell off the end of the pattern, or we're done. 7561cb0ef41Sopenharmony_ci if (fi === fl && pi === pl) { 7571cb0ef41Sopenharmony_ci // ran out of pattern and filename at the same time. 7581cb0ef41Sopenharmony_ci // an exact hit! 7591cb0ef41Sopenharmony_ci return true; 7601cb0ef41Sopenharmony_ci } 7611cb0ef41Sopenharmony_ci else if (fi === fl) { 7621cb0ef41Sopenharmony_ci // ran out of file, but still had pattern left. 7631cb0ef41Sopenharmony_ci // this is ok if we're doing the match as part of 7641cb0ef41Sopenharmony_ci // a glob fs traversal. 7651cb0ef41Sopenharmony_ci return partial; 7661cb0ef41Sopenharmony_ci } 7671cb0ef41Sopenharmony_ci else if (pi === pl) { 7681cb0ef41Sopenharmony_ci // ran out of pattern, still have file left. 7691cb0ef41Sopenharmony_ci // this is only acceptable if we're on the very last 7701cb0ef41Sopenharmony_ci // empty segment of a file with a trailing slash. 7711cb0ef41Sopenharmony_ci // a/* should match a/b/ 7721cb0ef41Sopenharmony_ci return fi === fl - 1 && file[fi] === ''; 7731cb0ef41Sopenharmony_ci /* c8 ignore start */ 7741cb0ef41Sopenharmony_ci } 7751cb0ef41Sopenharmony_ci else { 7761cb0ef41Sopenharmony_ci // should be unreachable. 7771cb0ef41Sopenharmony_ci throw new Error('wtf?'); 7781cb0ef41Sopenharmony_ci } 7791cb0ef41Sopenharmony_ci /* c8 ignore stop */ 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci braceExpand() { 7821cb0ef41Sopenharmony_ci return braceExpand(this.pattern, this.options); 7831cb0ef41Sopenharmony_ci } 7841cb0ef41Sopenharmony_ci parse(pattern) { 7851cb0ef41Sopenharmony_ci assertValidPattern(pattern); 7861cb0ef41Sopenharmony_ci const options = this.options; 7871cb0ef41Sopenharmony_ci // shortcuts 7881cb0ef41Sopenharmony_ci if (pattern === '**') 7891cb0ef41Sopenharmony_ci return GLOBSTAR; 7901cb0ef41Sopenharmony_ci if (pattern === '') 7911cb0ef41Sopenharmony_ci return ''; 7921cb0ef41Sopenharmony_ci // far and away, the most common glob pattern parts are 7931cb0ef41Sopenharmony_ci // *, *.*, and *.<ext> Add a fast check method for those. 7941cb0ef41Sopenharmony_ci let m; 7951cb0ef41Sopenharmony_ci let fastTest = null; 7961cb0ef41Sopenharmony_ci if ((m = pattern.match(starRE))) { 7971cb0ef41Sopenharmony_ci fastTest = options.dot ? starTestDot : starTest; 7981cb0ef41Sopenharmony_ci } 7991cb0ef41Sopenharmony_ci else if ((m = pattern.match(starDotExtRE))) { 8001cb0ef41Sopenharmony_ci fastTest = (options.nocase 8011cb0ef41Sopenharmony_ci ? options.dot 8021cb0ef41Sopenharmony_ci ? starDotExtTestNocaseDot 8031cb0ef41Sopenharmony_ci : starDotExtTestNocase 8041cb0ef41Sopenharmony_ci : options.dot 8051cb0ef41Sopenharmony_ci ? starDotExtTestDot 8061cb0ef41Sopenharmony_ci : starDotExtTest)(m[1]); 8071cb0ef41Sopenharmony_ci } 8081cb0ef41Sopenharmony_ci else if ((m = pattern.match(qmarksRE))) { 8091cb0ef41Sopenharmony_ci fastTest = (options.nocase 8101cb0ef41Sopenharmony_ci ? options.dot 8111cb0ef41Sopenharmony_ci ? qmarksTestNocaseDot 8121cb0ef41Sopenharmony_ci : qmarksTestNocase 8131cb0ef41Sopenharmony_ci : options.dot 8141cb0ef41Sopenharmony_ci ? qmarksTestDot 8151cb0ef41Sopenharmony_ci : qmarksTest)(m); 8161cb0ef41Sopenharmony_ci } 8171cb0ef41Sopenharmony_ci else if ((m = pattern.match(starDotStarRE))) { 8181cb0ef41Sopenharmony_ci fastTest = options.dot ? starDotStarTestDot : starDotStarTest; 8191cb0ef41Sopenharmony_ci } 8201cb0ef41Sopenharmony_ci else if ((m = pattern.match(dotStarRE))) { 8211cb0ef41Sopenharmony_ci fastTest = dotStarTest; 8221cb0ef41Sopenharmony_ci } 8231cb0ef41Sopenharmony_ci const re = AST.fromGlob(pattern, this.options).toMMPattern(); 8241cb0ef41Sopenharmony_ci return fastTest ? Object.assign(re, { test: fastTest }) : re; 8251cb0ef41Sopenharmony_ci } 8261cb0ef41Sopenharmony_ci makeRe() { 8271cb0ef41Sopenharmony_ci if (this.regexp || this.regexp === false) 8281cb0ef41Sopenharmony_ci return this.regexp; 8291cb0ef41Sopenharmony_ci // at this point, this.set is a 2d array of partial 8301cb0ef41Sopenharmony_ci // pattern strings, or "**". 8311cb0ef41Sopenharmony_ci // 8321cb0ef41Sopenharmony_ci // It's better to use .match(). This function shouldn't 8331cb0ef41Sopenharmony_ci // be used, really, but it's pretty convenient sometimes, 8341cb0ef41Sopenharmony_ci // when you just want to work with a regex. 8351cb0ef41Sopenharmony_ci const set = this.set; 8361cb0ef41Sopenharmony_ci if (!set.length) { 8371cb0ef41Sopenharmony_ci this.regexp = false; 8381cb0ef41Sopenharmony_ci return this.regexp; 8391cb0ef41Sopenharmony_ci } 8401cb0ef41Sopenharmony_ci const options = this.options; 8411cb0ef41Sopenharmony_ci const twoStar = options.noglobstar 8421cb0ef41Sopenharmony_ci ? star 8431cb0ef41Sopenharmony_ci : options.dot 8441cb0ef41Sopenharmony_ci ? twoStarDot 8451cb0ef41Sopenharmony_ci : twoStarNoDot; 8461cb0ef41Sopenharmony_ci const flags = new Set(options.nocase ? ['i'] : []); 8471cb0ef41Sopenharmony_ci // regexpify non-globstar patterns 8481cb0ef41Sopenharmony_ci // if ** is only item, then we just do one twoStar 8491cb0ef41Sopenharmony_ci // if ** is first, and there are more, prepend (\/|twoStar\/)? to next 8501cb0ef41Sopenharmony_ci // if ** is last, append (\/twoStar|) to previous 8511cb0ef41Sopenharmony_ci // if ** is in the middle, append (\/|\/twoStar\/) to previous 8521cb0ef41Sopenharmony_ci // then filter out GLOBSTAR symbols 8531cb0ef41Sopenharmony_ci let re = set 8541cb0ef41Sopenharmony_ci .map(pattern => { 8551cb0ef41Sopenharmony_ci const pp = pattern.map(p => { 8561cb0ef41Sopenharmony_ci if (p instanceof RegExp) { 8571cb0ef41Sopenharmony_ci for (const f of p.flags.split('')) 8581cb0ef41Sopenharmony_ci flags.add(f); 8591cb0ef41Sopenharmony_ci } 8601cb0ef41Sopenharmony_ci return typeof p === 'string' 8611cb0ef41Sopenharmony_ci ? regExpEscape(p) 8621cb0ef41Sopenharmony_ci : p === GLOBSTAR 8631cb0ef41Sopenharmony_ci ? GLOBSTAR 8641cb0ef41Sopenharmony_ci : p._src; 8651cb0ef41Sopenharmony_ci }); 8661cb0ef41Sopenharmony_ci pp.forEach((p, i) => { 8671cb0ef41Sopenharmony_ci const next = pp[i + 1]; 8681cb0ef41Sopenharmony_ci const prev = pp[i - 1]; 8691cb0ef41Sopenharmony_ci if (p !== GLOBSTAR || prev === GLOBSTAR) { 8701cb0ef41Sopenharmony_ci return; 8711cb0ef41Sopenharmony_ci } 8721cb0ef41Sopenharmony_ci if (prev === undefined) { 8731cb0ef41Sopenharmony_ci if (next !== undefined && next !== GLOBSTAR) { 8741cb0ef41Sopenharmony_ci pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next; 8751cb0ef41Sopenharmony_ci } 8761cb0ef41Sopenharmony_ci else { 8771cb0ef41Sopenharmony_ci pp[i] = twoStar; 8781cb0ef41Sopenharmony_ci } 8791cb0ef41Sopenharmony_ci } 8801cb0ef41Sopenharmony_ci else if (next === undefined) { 8811cb0ef41Sopenharmony_ci pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?'; 8821cb0ef41Sopenharmony_ci } 8831cb0ef41Sopenharmony_ci else if (next !== GLOBSTAR) { 8841cb0ef41Sopenharmony_ci pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next; 8851cb0ef41Sopenharmony_ci pp[i + 1] = GLOBSTAR; 8861cb0ef41Sopenharmony_ci } 8871cb0ef41Sopenharmony_ci }); 8881cb0ef41Sopenharmony_ci return pp.filter(p => p !== GLOBSTAR).join('/'); 8891cb0ef41Sopenharmony_ci }) 8901cb0ef41Sopenharmony_ci .join('|'); 8911cb0ef41Sopenharmony_ci // need to wrap in parens if we had more than one thing with |, 8921cb0ef41Sopenharmony_ci // otherwise only the first will be anchored to ^ and the last to $ 8931cb0ef41Sopenharmony_ci const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', '']; 8941cb0ef41Sopenharmony_ci // must match entire pattern 8951cb0ef41Sopenharmony_ci // ending in a * or ** will make it less strict. 8961cb0ef41Sopenharmony_ci re = '^' + open + re + close + '$'; 8971cb0ef41Sopenharmony_ci // can match anything, as long as it's not this. 8981cb0ef41Sopenharmony_ci if (this.negate) 8991cb0ef41Sopenharmony_ci re = '^(?!' + re + ').+$'; 9001cb0ef41Sopenharmony_ci try { 9011cb0ef41Sopenharmony_ci this.regexp = new RegExp(re, [...flags].join('')); 9021cb0ef41Sopenharmony_ci /* c8 ignore start */ 9031cb0ef41Sopenharmony_ci } 9041cb0ef41Sopenharmony_ci catch (ex) { 9051cb0ef41Sopenharmony_ci // should be impossible 9061cb0ef41Sopenharmony_ci this.regexp = false; 9071cb0ef41Sopenharmony_ci } 9081cb0ef41Sopenharmony_ci /* c8 ignore stop */ 9091cb0ef41Sopenharmony_ci return this.regexp; 9101cb0ef41Sopenharmony_ci } 9111cb0ef41Sopenharmony_ci slashSplit(p) { 9121cb0ef41Sopenharmony_ci // if p starts with // on windows, we preserve that 9131cb0ef41Sopenharmony_ci // so that UNC paths aren't broken. Otherwise, any number of 9141cb0ef41Sopenharmony_ci // / characters are coalesced into one, unless 9151cb0ef41Sopenharmony_ci // preserveMultipleSlashes is set to true. 9161cb0ef41Sopenharmony_ci if (this.preserveMultipleSlashes) { 9171cb0ef41Sopenharmony_ci return p.split('/'); 9181cb0ef41Sopenharmony_ci } 9191cb0ef41Sopenharmony_ci else if (this.isWindows && /^\/\/[^\/]+/.test(p)) { 9201cb0ef41Sopenharmony_ci // add an extra '' for the one we lose 9211cb0ef41Sopenharmony_ci return ['', ...p.split(/\/+/)]; 9221cb0ef41Sopenharmony_ci } 9231cb0ef41Sopenharmony_ci else { 9241cb0ef41Sopenharmony_ci return p.split(/\/+/); 9251cb0ef41Sopenharmony_ci } 9261cb0ef41Sopenharmony_ci } 9271cb0ef41Sopenharmony_ci match(f, partial = this.partial) { 9281cb0ef41Sopenharmony_ci this.debug('match', f, this.pattern); 9291cb0ef41Sopenharmony_ci // short-circuit in the case of busted things. 9301cb0ef41Sopenharmony_ci // comments, etc. 9311cb0ef41Sopenharmony_ci if (this.comment) { 9321cb0ef41Sopenharmony_ci return false; 9331cb0ef41Sopenharmony_ci } 9341cb0ef41Sopenharmony_ci if (this.empty) { 9351cb0ef41Sopenharmony_ci return f === ''; 9361cb0ef41Sopenharmony_ci } 9371cb0ef41Sopenharmony_ci if (f === '/' && partial) { 9381cb0ef41Sopenharmony_ci return true; 9391cb0ef41Sopenharmony_ci } 9401cb0ef41Sopenharmony_ci const options = this.options; 9411cb0ef41Sopenharmony_ci // windows: need to use /, not \ 9421cb0ef41Sopenharmony_ci if (this.isWindows) { 9431cb0ef41Sopenharmony_ci f = f.split('\\').join('/'); 9441cb0ef41Sopenharmony_ci } 9451cb0ef41Sopenharmony_ci // treat the test path as a set of pathparts. 9461cb0ef41Sopenharmony_ci const ff = this.slashSplit(f); 9471cb0ef41Sopenharmony_ci this.debug(this.pattern, 'split', ff); 9481cb0ef41Sopenharmony_ci // just ONE of the pattern sets in this.set needs to match 9491cb0ef41Sopenharmony_ci // in order for it to be valid. If negating, then just one 9501cb0ef41Sopenharmony_ci // match means that we have failed. 9511cb0ef41Sopenharmony_ci // Either way, return on the first hit. 9521cb0ef41Sopenharmony_ci const set = this.set; 9531cb0ef41Sopenharmony_ci this.debug(this.pattern, 'set', set); 9541cb0ef41Sopenharmony_ci // Find the basename of the path by looking for the last non-empty segment 9551cb0ef41Sopenharmony_ci let filename = ff[ff.length - 1]; 9561cb0ef41Sopenharmony_ci if (!filename) { 9571cb0ef41Sopenharmony_ci for (let i = ff.length - 2; !filename && i >= 0; i--) { 9581cb0ef41Sopenharmony_ci filename = ff[i]; 9591cb0ef41Sopenharmony_ci } 9601cb0ef41Sopenharmony_ci } 9611cb0ef41Sopenharmony_ci for (let i = 0; i < set.length; i++) { 9621cb0ef41Sopenharmony_ci const pattern = set[i]; 9631cb0ef41Sopenharmony_ci let file = ff; 9641cb0ef41Sopenharmony_ci if (options.matchBase && pattern.length === 1) { 9651cb0ef41Sopenharmony_ci file = [filename]; 9661cb0ef41Sopenharmony_ci } 9671cb0ef41Sopenharmony_ci const hit = this.matchOne(file, pattern, partial); 9681cb0ef41Sopenharmony_ci if (hit) { 9691cb0ef41Sopenharmony_ci if (options.flipNegate) { 9701cb0ef41Sopenharmony_ci return true; 9711cb0ef41Sopenharmony_ci } 9721cb0ef41Sopenharmony_ci return !this.negate; 9731cb0ef41Sopenharmony_ci } 9741cb0ef41Sopenharmony_ci } 9751cb0ef41Sopenharmony_ci // didn't get any hits. this is success if it's a negative 9761cb0ef41Sopenharmony_ci // pattern, failure otherwise. 9771cb0ef41Sopenharmony_ci if (options.flipNegate) { 9781cb0ef41Sopenharmony_ci return false; 9791cb0ef41Sopenharmony_ci } 9801cb0ef41Sopenharmony_ci return this.negate; 9811cb0ef41Sopenharmony_ci } 9821cb0ef41Sopenharmony_ci static defaults(def) { 9831cb0ef41Sopenharmony_ci return minimatch.defaults(def).Minimatch; 9841cb0ef41Sopenharmony_ci } 9851cb0ef41Sopenharmony_ci} 9861cb0ef41Sopenharmony_ci/* c8 ignore start */ 9871cb0ef41Sopenharmony_ciexport { AST } from './ast.js'; 9881cb0ef41Sopenharmony_ciexport { escape } from './escape.js'; 9891cb0ef41Sopenharmony_ciexport { unescape } from './unescape.js'; 9901cb0ef41Sopenharmony_ci/* c8 ignore stop */ 9911cb0ef41Sopenharmony_ciminimatch.AST = AST; 9921cb0ef41Sopenharmony_ciminimatch.Minimatch = Minimatch; 9931cb0ef41Sopenharmony_ciminimatch.escape = escape; 9941cb0ef41Sopenharmony_ciminimatch.unescape = unescape; 9951cb0ef41Sopenharmony_ci//# sourceMappingURL=index.js.map