Buckets:
| ; | |
| var __importDefault = (this && this.__importDefault) || function (mod) { | |
| return (mod && mod.__esModule) ? mod : { "default": mod }; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| exports.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; | |
| const brace_expansion_1 = __importDefault(require("brace-expansion")); | |
| const assert_valid_pattern_js_1 = require("./assert-valid-pattern.js"); | |
| const ast_js_1 = require("./ast.js"); | |
| const escape_js_1 = require("./escape.js"); | |
| const unescape_js_1 = require("./unescape.js"); | |
| const minimatch = (p, pattern, options = {}) => { | |
| (0, assert_valid_pattern_js_1.assertValidPattern)(pattern); | |
| // shortcut: comments match nothing. | |
| if (!options.nocomment && pattern.charAt(0) === '#') { | |
| return false; | |
| } | |
| return new Minimatch(pattern, options).match(p); | |
| }; | |
| exports.minimatch = minimatch; | |
| // Optimized checking for the most common glob patterns. | |
| const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/; | |
| const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext); | |
| const starDotExtTestDot = (ext) => (f) => f.endsWith(ext); | |
| const starDotExtTestNocase = (ext) => { | |
| ext = ext.toLowerCase(); | |
| return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext); | |
| }; | |
| const starDotExtTestNocaseDot = (ext) => { | |
| ext = ext.toLowerCase(); | |
| return (f) => f.toLowerCase().endsWith(ext); | |
| }; | |
| const starDotStarRE = /^\*+\.\*+$/; | |
| const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.'); | |
| const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.'); | |
| const dotStarRE = /^\.\*+$/; | |
| const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.'); | |
| const starRE = /^\*+$/; | |
| const starTest = (f) => f.length !== 0 && !f.startsWith('.'); | |
| const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..'; | |
| const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/; | |
| const qmarksTestNocase = ([$0, ext = '']) => { | |
| const noext = qmarksTestNoExt([$0]); | |
| if (!ext) | |
| return noext; | |
| ext = ext.toLowerCase(); | |
| return (f) => noext(f) && f.toLowerCase().endsWith(ext); | |
| }; | |
| const qmarksTestNocaseDot = ([$0, ext = '']) => { | |
| const noext = qmarksTestNoExtDot([$0]); | |
| if (!ext) | |
| return noext; | |
| ext = ext.toLowerCase(); | |
| return (f) => noext(f) && f.toLowerCase().endsWith(ext); | |
| }; | |
| const qmarksTestDot = ([$0, ext = '']) => { | |
| const noext = qmarksTestNoExtDot([$0]); | |
| return !ext ? noext : (f) => noext(f) && f.endsWith(ext); | |
| }; | |
| const qmarksTest = ([$0, ext = '']) => { | |
| const noext = qmarksTestNoExt([$0]); | |
| return !ext ? noext : (f) => noext(f) && f.endsWith(ext); | |
| }; | |
| const qmarksTestNoExt = ([$0]) => { | |
| const len = $0.length; | |
| return (f) => f.length === len && !f.startsWith('.'); | |
| }; | |
| const qmarksTestNoExtDot = ([$0]) => { | |
| const len = $0.length; | |
| return (f) => f.length === len && f !== '.' && f !== '..'; | |
| }; | |
| /* c8 ignore start */ | |
| const defaultPlatform = (typeof process === 'object' && process | |
| ? (typeof process.env === 'object' && | |
| process.env && | |
| process.env.__MINIMATCH_TESTING_PLATFORM__) || | |
| process.platform | |
| : 'posix'); | |
| const path = { | |
| win32: { sep: '\\' }, | |
| posix: { sep: '/' }, | |
| }; | |
| /* c8 ignore stop */ | |
| exports.sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep; | |
| exports.minimatch.sep = exports.sep; | |
| exports.GLOBSTAR = Symbol('globstar **'); | |
| exports.minimatch.GLOBSTAR = exports.GLOBSTAR; | |
| // any single thing other than / | |
| // don't need to escape / when using new RegExp() | |
| const qmark = '[^/]'; | |
| // * => any number of characters | |
| const star = qmark + '*?'; | |
| // ** when dots are allowed. Anything goes, except .. and . | |
| // not (^ or / followed by one or two dots followed by $ or /), | |
| // followed by anything, any number of times. | |
| const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?'; | |
| // not a ^ or / followed by a dot, | |
| // followed by anything, any number of times. | |
| const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?'; | |
| const filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options); | |
| exports.filter = filter; | |
| exports.minimatch.filter = exports.filter; | |
| const ext = (a, b = {}) => Object.assign({}, a, b); | |
| const defaults = (def) => { | |
| if (!def || typeof def !== 'object' || !Object.keys(def).length) { | |
| return exports.minimatch; | |
| } | |
| const orig = exports.minimatch; | |
| const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options)); | |
| return Object.assign(m, { | |
| Minimatch: class Minimatch extends orig.Minimatch { | |
| constructor(pattern, options = {}) { | |
| super(pattern, ext(def, options)); | |
| } | |
| static defaults(options) { | |
| return orig.defaults(ext(def, options)).Minimatch; | |
| } | |
| }, | |
| AST: class AST extends orig.AST { | |
| /* c8 ignore start */ | |
| constructor(type, parent, options = {}) { | |
| super(type, parent, ext(def, options)); | |
| } | |
| /* c8 ignore stop */ | |
| static fromGlob(pattern, options = {}) { | |
| return orig.AST.fromGlob(pattern, ext(def, options)); | |
| } | |
| }, | |
| unescape: (s, options = {}) => orig.unescape(s, ext(def, options)), | |
| escape: (s, options = {}) => orig.escape(s, ext(def, options)), | |
| filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)), | |
| defaults: (options) => orig.defaults(ext(def, options)), | |
| makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)), | |
| braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)), | |
| match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)), | |
| sep: orig.sep, | |
| GLOBSTAR: exports.GLOBSTAR, | |
| }); | |
| }; | |
| exports.defaults = defaults; | |
| exports.minimatch.defaults = exports.defaults; | |
| // Brace expansion: | |
| // a{b,c}d -> abd acd | |
| // a{b,}c -> abc ac | |
| // a{0..3}d -> a0d a1d a2d a3d | |
| // a{b,c{d,e}f}g -> abg acdfg acefg | |
| // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg | |
| // | |
| // Invalid sets are not expanded. | |
| // a{2..}b -> a{2..}b | |
| // a{b}c -> a{b}c | |
| const braceExpand = (pattern, options = {}) => { | |
| (0, assert_valid_pattern_js_1.assertValidPattern)(pattern); | |
| // Thanks to Yeting Li <https://github.com/yetingli> for | |
| // improving this regexp to avoid a ReDOS vulnerability. | |
| if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) { | |
| // shortcut. no need to expand. | |
| return [pattern]; | |
| } | |
| return (0, brace_expansion_1.default)(pattern); | |
| }; | |
| exports.braceExpand = braceExpand; | |
| exports.minimatch.braceExpand = exports.braceExpand; | |
| // parse a component of the expanded set. | |
| // At this point, no pattern may contain "/" in it | |
| // so we're going to return a 2d array, where each entry is the full | |
| // pattern, split on '/', and then turned into a regular expression. | |
| // A regexp is made at the end which joins each array with an | |
| // escaped /, and another full one which joins each regexp with |. | |
| // | |
| // Following the lead of Bash 4.1, note that "**" only has special meaning | |
| // when it is the *only* thing in a path portion. Otherwise, any series | |
| // of * is equivalent to a single *. Globstar behavior is enabled by | |
| // default, and can be disabled by setting options.noglobstar. | |
| const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe(); | |
| exports.makeRe = makeRe; | |
| exports.minimatch.makeRe = exports.makeRe; | |
| const match = (list, pattern, options = {}) => { | |
| const mm = new Minimatch(pattern, options); | |
| list = list.filter(f => mm.match(f)); | |
| if (mm.options.nonull && !list.length) { | |
| list.push(pattern); | |
| } | |
| return list; | |
| }; | |
| exports.match = match; | |
| exports.minimatch.match = exports.match; | |
| // replace stuff like \* with * | |
| const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/; | |
| const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); | |
| class Minimatch { | |
| options; | |
| set; | |
| pattern; | |
| windowsPathsNoEscape; | |
| nonegate; | |
| negate; | |
| comment; | |
| empty; | |
| preserveMultipleSlashes; | |
| partial; | |
| globSet; | |
| globParts; | |
| nocase; | |
| isWindows; | |
| platform; | |
| windowsNoMagicRoot; | |
| maxGlobstarRecursion; | |
| regexp; | |
| constructor(pattern, options = {}) { | |
| (0, assert_valid_pattern_js_1.assertValidPattern)(pattern); | |
| options = options || {}; | |
| this.options = options; | |
| this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200; | |
| this.pattern = pattern; | |
| this.platform = options.platform || defaultPlatform; | |
| this.isWindows = this.platform === 'win32'; | |
| this.windowsPathsNoEscape = | |
| !!options.windowsPathsNoEscape || options.allowWindowsEscape === false; | |
| if (this.windowsPathsNoEscape) { | |
| this.pattern = this.pattern.replace(/\\/g, '/'); | |
| } | |
| this.preserveMultipleSlashes = !!options.preserveMultipleSlashes; | |
| this.regexp = null; | |
| this.negate = false; | |
| this.nonegate = !!options.nonegate; | |
| this.comment = false; | |
| this.empty = false; | |
| this.partial = !!options.partial; | |
| this.nocase = !!this.options.nocase; | |
| this.windowsNoMagicRoot = | |
| options.windowsNoMagicRoot !== undefined | |
| ? options.windowsNoMagicRoot | |
| : !!(this.isWindows && this.nocase); | |
| this.globSet = []; | |
| this.globParts = []; | |
| this.set = []; | |
| // make the set of regexps etc. | |
| this.make(); | |
| } | |
| hasMagic() { | |
| if (this.options.magicalBraces && this.set.length > 1) { | |
| return true; | |
| } | |
| for (const pattern of this.set) { | |
| for (const part of pattern) { | |
| if (typeof part !== 'string') | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| debug(..._) { } | |
| make() { | |
| const pattern = this.pattern; | |
| const options = this.options; | |
| // empty patterns and comments match nothing. | |
| if (!options.nocomment && pattern.charAt(0) === '#') { | |
| this.comment = true; | |
| return; | |
| } | |
| if (!pattern) { | |
| this.empty = true; | |
| return; | |
| } | |
| // step 1: figure out negation, etc. | |
| this.parseNegate(); | |
| // step 2: expand braces | |
| this.globSet = [...new Set(this.braceExpand())]; | |
| if (options.debug) { | |
| this.debug = (...args) => console.error(...args); | |
| } | |
| this.debug(this.pattern, this.globSet); | |
| // step 3: now we have a set, so turn each one into a series of | |
| // path-portion matching patterns. | |
| // These will be regexps, except in the case of "**", which is | |
| // set to the GLOBSTAR object for globstar behavior, | |
| // and will not contain any / characters | |
| // | |
| // First, we preprocess to make the glob pattern sets a bit simpler | |
| // and deduped. There are some perf-killing patterns that can cause | |
| // problems with a glob walk, but we can simplify them down a bit. | |
| const rawGlobParts = this.globSet.map(s => this.slashSplit(s)); | |
| this.globParts = this.preprocess(rawGlobParts); | |
| this.debug(this.pattern, this.globParts); | |
| // glob --> regexps | |
| let set = this.globParts.map((s, _, __) => { | |
| if (this.isWindows && this.windowsNoMagicRoot) { | |
| // check if it's a drive or unc path. | |
| const isUNC = s[0] === '' && | |
| s[1] === '' && | |
| (s[2] === '?' || !globMagic.test(s[2])) && | |
| !globMagic.test(s[3]); | |
| const isDrive = /^[a-z]:/i.test(s[0]); | |
| if (isUNC) { | |
| return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))]; | |
| } | |
| else if (isDrive) { | |
| return [s[0], ...s.slice(1).map(ss => this.parse(ss))]; | |
| } | |
| } | |
| return s.map(ss => this.parse(ss)); | |
| }); | |
| this.debug(this.pattern, set); | |
| // filter out everything that didn't compile properly. | |
| this.set = set.filter(s => s.indexOf(false) === -1); | |
| // do not treat the ? in UNC paths as magic | |
| if (this.isWindows) { | |
| for (let i = 0; i < this.set.length; i++) { | |
| const p = this.set[i]; | |
| if (p[0] === '' && | |
| p[1] === '' && | |
| this.globParts[i][2] === '?' && | |
| typeof p[3] === 'string' && | |
| /^[a-z]:$/i.test(p[3])) { | |
| p[2] = '?'; | |
| } | |
| } | |
| } | |
| this.debug(this.pattern, this.set); | |
| } | |
| // various transforms to equivalent pattern sets that are | |
| // faster to process in a filesystem walk. The goal is to | |
| // eliminate what we can, and push all ** patterns as far | |
| // to the right as possible, even if it increases the number | |
| // of patterns that we have to process. | |
| preprocess(globParts) { | |
| // if we're not in globstar mode, then turn all ** into * | |
| if (this.options.noglobstar) { | |
| for (let i = 0; i < globParts.length; i++) { | |
| for (let j = 0; j < globParts[i].length; j++) { | |
| if (globParts[i][j] === '**') { | |
| globParts[i][j] = '*'; | |
| } | |
| } | |
| } | |
| } | |
| const { optimizationLevel = 1 } = this.options; | |
| if (optimizationLevel >= 2) { | |
| // aggressive optimization for the purpose of fs walking | |
| globParts = this.firstPhasePreProcess(globParts); | |
| globParts = this.secondPhasePreProcess(globParts); | |
| } | |
| else if (optimizationLevel >= 1) { | |
| // just basic optimizations to remove some .. parts | |
| globParts = this.levelOneOptimize(globParts); | |
| } | |
| else { | |
| // just collapse multiple ** portions into one | |
| globParts = this.adjascentGlobstarOptimize(globParts); | |
| } | |
| return globParts; | |
| } | |
| // just get rid of adjascent ** portions | |
| adjascentGlobstarOptimize(globParts) { | |
| return globParts.map(parts => { | |
| let gs = -1; | |
| while (-1 !== (gs = parts.indexOf('**', gs + 1))) { | |
| let i = gs; | |
| while (parts[i + 1] === '**') { | |
| i++; | |
| } | |
| if (i !== gs) { | |
| parts.splice(gs, i - gs); | |
| } | |
| } | |
| return parts; | |
| }); | |
| } | |
| // get rid of adjascent ** and resolve .. portions | |
| levelOneOptimize(globParts) { | |
| return globParts.map(parts => { | |
| parts = parts.reduce((set, part) => { | |
| const prev = set[set.length - 1]; | |
| if (part === '**' && prev === '**') { | |
| return set; | |
| } | |
| if (part === '..') { | |
| if (prev && prev !== '..' && prev !== '.' && prev !== '**') { | |
| set.pop(); | |
| return set; | |
| } | |
| } | |
| set.push(part); | |
| return set; | |
| }, []); | |
| return parts.length === 0 ? [''] : parts; | |
| }); | |
| } | |
| levelTwoFileOptimize(parts) { | |
| if (!Array.isArray(parts)) { | |
| parts = this.slashSplit(parts); | |
| } | |
| let didSomething = false; | |
| do { | |
| didSomething = false; | |
| // <pre>/<e>/<rest> -> <pre>/<rest> | |
| if (!this.preserveMultipleSlashes) { | |
| for (let i = 1; i < parts.length - 1; i++) { | |
| const p = parts[i]; | |
| // don't squeeze out UNC patterns | |
| if (i === 1 && p === '' && parts[0] === '') | |
| continue; | |
| if (p === '.' || p === '') { | |
| didSomething = true; | |
| parts.splice(i, 1); | |
| i--; | |
| } | |
| } | |
| if (parts[0] === '.' && | |
| parts.length === 2 && | |
| (parts[1] === '.' || parts[1] === '')) { | |
| didSomething = true; | |
| parts.pop(); | |
| } | |
| } | |
| // <pre>/<p>/../<rest> -> <pre>/<rest> | |
| let dd = 0; | |
| while (-1 !== (dd = parts.indexOf('..', dd + 1))) { | |
| const p = parts[dd - 1]; | |
| if (p && p !== '.' && p !== '..' && p !== '**') { | |
| didSomething = true; | |
| parts.splice(dd - 1, 2); | |
| dd -= 2; | |
| } | |
| } | |
| } while (didSomething); | |
| return parts.length === 0 ? [''] : parts; | |
| } | |
| // First phase: single-pattern processing | |
| // <pre> is 1 or more portions | |
| // <rest> is 1 or more portions | |
| // <p> is any portion other than ., .., '', or ** | |
| // <e> is . or '' | |
| // | |
| // **/.. is *brutal* for filesystem walking performance, because | |
| // it effectively resets the recursive walk each time it occurs, | |
| // and ** cannot be reduced out by a .. pattern part like a regexp | |
| // or most strings (other than .., ., and '') can be. | |
| // | |
| // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>} | |
| // <pre>/<e>/<rest> -> <pre>/<rest> | |
| // <pre>/<p>/../<rest> -> <pre>/<rest> | |
| // **/**/<rest> -> **/<rest> | |
| // | |
| // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow | |
| // this WOULD be allowed if ** did follow symlinks, or * didn't | |
| firstPhasePreProcess(globParts) { | |
| let didSomething = false; | |
| do { | |
| didSomething = false; | |
| // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>} | |
| for (let parts of globParts) { | |
| let gs = -1; | |
| while (-1 !== (gs = parts.indexOf('**', gs + 1))) { | |
| let gss = gs; | |
| while (parts[gss + 1] === '**') { | |
| // <pre>/**/**/<rest> -> <pre>/**/<rest> | |
| gss++; | |
| } | |
| // eg, if gs is 2 and gss is 4, that means we have 3 ** | |
| // parts, and can remove 2 of them. | |
| if (gss > gs) { | |
| parts.splice(gs + 1, gss - gs); | |
| } | |
| let next = parts[gs + 1]; | |
| const p = parts[gs + 2]; | |
| const p2 = parts[gs + 3]; | |
| if (next !== '..') | |
| continue; | |
| if (!p || | |
| p === '.' || | |
| p === '..' || | |
| !p2 || | |
| p2 === '.' || | |
| p2 === '..') { | |
| continue; | |
| } | |
| didSomething = true; | |
| // edit parts in place, and push the new one | |
| parts.splice(gs, 1); | |
| const other = parts.slice(0); | |
| other[gs] = '**'; | |
| globParts.push(other); | |
| gs--; | |
| } | |
| // <pre>/<e>/<rest> -> <pre>/<rest> | |
| if (!this.preserveMultipleSlashes) { | |
| for (let i = 1; i < parts.length - 1; i++) { | |
| const p = parts[i]; | |
| // don't squeeze out UNC patterns | |
| if (i === 1 && p === '' && parts[0] === '') | |
| continue; | |
| if (p === '.' || p === '') { | |
| didSomething = true; | |
| parts.splice(i, 1); | |
| i--; | |
| } | |
| } | |
| if (parts[0] === '.' && | |
| parts.length === 2 && | |
| (parts[1] === '.' || parts[1] === '')) { | |
| didSomething = true; | |
| parts.pop(); | |
| } | |
| } | |
| // <pre>/<p>/../<rest> -> <pre>/<rest> | |
| let dd = 0; | |
| while (-1 !== (dd = parts.indexOf('..', dd + 1))) { | |
| const p = parts[dd - 1]; | |
| if (p && p !== '.' && p !== '..' && p !== '**') { | |
| didSomething = true; | |
| const needDot = dd === 1 && parts[dd + 1] === '**'; | |
| const splin = needDot ? ['.'] : []; | |
| parts.splice(dd - 1, 2, ...splin); | |
| if (parts.length === 0) | |
| parts.push(''); | |
| dd -= 2; | |
| } | |
| } | |
| } | |
| } while (didSomething); | |
| return globParts; | |
| } | |
| // second phase: multi-pattern dedupes | |
| // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest> | |
| // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest> | |
| // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest> | |
| // | |
| // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest> | |
| // ^-- not valid because ** doens't follow symlinks | |
| secondPhasePreProcess(globParts) { | |
| for (let i = 0; i < globParts.length - 1; i++) { | |
| for (let j = i + 1; j < globParts.length; j++) { | |
| const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes); | |
| if (matched) { | |
| globParts[i] = []; | |
| globParts[j] = matched; | |
| break; | |
| } | |
| } | |
| } | |
| return globParts.filter(gs => gs.length); | |
| } | |
| partsMatch(a, b, emptyGSMatch = false) { | |
| let ai = 0; | |
| let bi = 0; | |
| let result = []; | |
| let which = ''; | |
| while (ai < a.length && bi < b.length) { | |
| if (a[ai] === b[bi]) { | |
| result.push(which === 'b' ? b[bi] : a[ai]); | |
| ai++; | |
| bi++; | |
| } | |
| else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) { | |
| result.push(a[ai]); | |
| ai++; | |
| } | |
| else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) { | |
| result.push(b[bi]); | |
| bi++; | |
| } | |
| else if (a[ai] === '*' && | |
| b[bi] && | |
| (this.options.dot || !b[bi].startsWith('.')) && | |
| b[bi] !== '**') { | |
| if (which === 'b') | |
| return false; | |
| which = 'a'; | |
| result.push(a[ai]); | |
| ai++; | |
| bi++; | |
| } | |
| else if (b[bi] === '*' && | |
| a[ai] && | |
| (this.options.dot || !a[ai].startsWith('.')) && | |
| a[ai] !== '**') { | |
| if (which === 'a') | |
| return false; | |
| which = 'b'; | |
| result.push(b[bi]); | |
| ai++; | |
| bi++; | |
| } | |
| else { | |
| return false; | |
| } | |
| } | |
| // if we fall out of the loop, it means they two are identical | |
| // as long as their lengths match | |
| return a.length === b.length && result; | |
| } | |
| parseNegate() { | |
| if (this.nonegate) | |
| return; | |
| const pattern = this.pattern; | |
| let negate = false; | |
| let negateOffset = 0; | |
| for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) { | |
| negate = !negate; | |
| negateOffset++; | |
| } | |
| if (negateOffset) | |
| this.pattern = pattern.slice(negateOffset); | |
| this.negate = negate; | |
| } | |
| // set partial to true to test if, for example, | |
| // "/a/b" matches the start of "/*/b/*/d" | |
| // Partial means, if you run out of file before you run | |
| // out of pattern, then that's fine, as long as all | |
| // the parts match. | |
| matchOne(file, pattern, partial = false) { | |
| let fileStartIndex = 0; | |
| let patternStartIndex = 0; | |
| // UNC paths like //?/X:/... can match X:/... and vice versa | |
| // Drive letters in absolute drive or unc paths are always compared | |
| // case-insensitively. | |
| if (this.isWindows) { | |
| const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]); | |
| const fileUNC = !fileDrive && | |
| file[0] === '' && | |
| file[1] === '' && | |
| file[2] === '?' && | |
| /^[a-z]:$/i.test(file[3]); | |
| const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]); | |
| const patternUNC = !patternDrive && | |
| pattern[0] === '' && | |
| pattern[1] === '' && | |
| pattern[2] === '?' && | |
| typeof pattern[3] === 'string' && | |
| /^[a-z]:$/i.test(pattern[3]); | |
| const fdi = fileUNC ? 3 : fileDrive ? 0 : undefined; | |
| const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined; | |
| if (typeof fdi === 'number' && typeof pdi === 'number') { | |
| const [fd, pd] = [ | |
| file[fdi], | |
| pattern[pdi], | |
| ]; | |
| if (fd.toLowerCase() === pd.toLowerCase()) { | |
| pattern[pdi] = fd; | |
| patternStartIndex = pdi; | |
| fileStartIndex = fdi; | |
| } | |
| } | |
| } | |
| // resolve and reduce . and .. portions in the file as well. | |
| // dont' need to do the second phase, because it's only one string[] | |
| const { optimizationLevel = 1 } = this.options; | |
| if (optimizationLevel >= 2) { | |
| file = this.levelTwoFileOptimize(file); | |
| } | |
| if (pattern.includes(exports.GLOBSTAR)) { | |
| return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex); | |
| } | |
| return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex); | |
| } | |
| #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) { | |
| const firstgs = pattern.indexOf(exports.GLOBSTAR, patternIndex); | |
| const lastgs = pattern.lastIndexOf(exports.GLOBSTAR); | |
| const [head, body, tail] = partial ? [ | |
| pattern.slice(patternIndex, firstgs), | |
| pattern.slice(firstgs + 1), | |
| [], | |
| ] : [ | |
| pattern.slice(patternIndex, firstgs), | |
| pattern.slice(firstgs + 1, lastgs), | |
| pattern.slice(lastgs + 1), | |
| ]; | |
| if (head.length) { | |
| const fileHead = file.slice(fileIndex, fileIndex + head.length); | |
| if (!this.#matchOne(fileHead, head, partial, 0, 0)) | |
| return false; | |
| fileIndex += head.length; | |
| } | |
| let fileTailMatch = 0; | |
| if (tail.length) { | |
| if (tail.length + fileIndex > file.length) | |
| return false; | |
| let tailStart = file.length - tail.length; | |
| if (this.#matchOne(file, tail, partial, tailStart, 0)) { | |
| fileTailMatch = tail.length; | |
| } | |
| else { | |
| if (file[file.length - 1] !== '' || | |
| fileIndex + tail.length === file.length) { | |
| return false; | |
| } | |
| tailStart--; | |
| if (!this.#matchOne(file, tail, partial, tailStart, 0)) | |
| return false; | |
| fileTailMatch = tail.length + 1; | |
| } | |
| } | |
| if (!body.length) { | |
| let sawSome = !!fileTailMatch; | |
| for (let i = fileIndex; i < file.length - fileTailMatch; i++) { | |
| const f = String(file[i]); | |
| sawSome = true; | |
| if (f === '.' || f === '..' || | |
| (!this.options.dot && f.startsWith('.'))) { | |
| return false; | |
| } | |
| } | |
| return partial || sawSome; | |
| } | |
| const bodySegments = [[[], 0]]; | |
| let currentBody = bodySegments[0]; | |
| let nonGsParts = 0; | |
| const nonGsPartsSums = [0]; | |
| for (const b of body) { | |
| if (b === exports.GLOBSTAR) { | |
| nonGsPartsSums.push(nonGsParts); | |
| currentBody = [[], 0]; | |
| bodySegments.push(currentBody); | |
| } | |
| else { | |
| currentBody[0].push(b); | |
| nonGsParts++; | |
| } | |
| } | |
| let i = bodySegments.length - 1; | |
| const fileLength = file.length - fileTailMatch; | |
| for (const b of bodySegments) { | |
| b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length); | |
| } | |
| return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch); | |
| } | |
| #matchGlobStarBodySections(file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) { | |
| const bs = bodySegments[bodyIndex]; | |
| if (!bs) { | |
| for (let i = fileIndex; i < file.length; i++) { | |
| sawTail = true; | |
| const f = file[i]; | |
| if (f === '.' || f === '..' || | |
| (!this.options.dot && f.startsWith('.'))) { | |
| return false; | |
| } | |
| } | |
| return sawTail; | |
| } | |
| const [body, after] = bs; | |
| while (fileIndex <= after) { | |
| const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0); | |
| if (m && globStarDepth < this.maxGlobstarRecursion) { | |
| const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail); | |
| if (sub !== false) | |
| return sub; | |
| } | |
| const f = file[fileIndex]; | |
| if (f === '.' || f === '..' || | |
| (!this.options.dot && f.startsWith('.'))) { | |
| return false; | |
| } | |
| fileIndex++; | |
| } | |
| return partial || null; | |
| } | |
| #matchOne(file, pattern, partial, fileIndex, patternIndex) { | |
| let fi; | |
| let pi; | |
| let pl; | |
| let fl; | |
| for (fi = fileIndex, pi = patternIndex, | |
| fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) { | |
| this.debug('matchOne loop'); | |
| let p = pattern[pi]; | |
| let f = file[fi]; | |
| this.debug(pattern, p, f); | |
| /* c8 ignore start */ | |
| if (p === false || p === exports.GLOBSTAR) | |
| return false; | |
| /* c8 ignore stop */ | |
| let hit; | |
| if (typeof p === 'string') { | |
| hit = f === p; | |
| this.debug('string match', p, f, hit); | |
| } | |
| else { | |
| hit = p.test(f); | |
| this.debug('pattern match', p, f, hit); | |
| } | |
| if (!hit) | |
| return false; | |
| } | |
| if (fi === fl && pi === pl) { | |
| return true; | |
| } | |
| else if (fi === fl) { | |
| return partial; | |
| } | |
| else if (pi === pl) { | |
| return fi === fl - 1 && file[fi] === ''; | |
| /* c8 ignore start */ | |
| } | |
| else { | |
| throw new Error('wtf?'); | |
| } | |
| /* c8 ignore stop */ | |
| } | |
| braceExpand() { | |
| return (0, exports.braceExpand)(this.pattern, this.options); | |
| } | |
| parse(pattern) { | |
| (0, assert_valid_pattern_js_1.assertValidPattern)(pattern); | |
| const options = this.options; | |
| // shortcuts | |
| if (pattern === '**') | |
| return exports.GLOBSTAR; | |
| if (pattern === '') | |
| return ''; | |
| // far and away, the most common glob pattern parts are | |
| // *, *.*, and *.<ext> Add a fast check method for those. | |
| let m; | |
| let fastTest = null; | |
| if ((m = pattern.match(starRE))) { | |
| fastTest = options.dot ? starTestDot : starTest; | |
| } | |
| else if ((m = pattern.match(starDotExtRE))) { | |
| fastTest = (options.nocase | |
| ? options.dot | |
| ? starDotExtTestNocaseDot | |
| : starDotExtTestNocase | |
| : options.dot | |
| ? starDotExtTestDot | |
| : starDotExtTest)(m[1]); | |
| } | |
| else if ((m = pattern.match(qmarksRE))) { | |
| fastTest = (options.nocase | |
| ? options.dot | |
| ? qmarksTestNocaseDot | |
| : qmarksTestNocase | |
| : options.dot | |
| ? qmarksTestDot | |
| : qmarksTest)(m); | |
| } | |
| else if ((m = pattern.match(starDotStarRE))) { | |
| fastTest = options.dot ? starDotStarTestDot : starDotStarTest; | |
| } | |
| else if ((m = pattern.match(dotStarRE))) { | |
| fastTest = dotStarTest; | |
| } | |
| const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern(); | |
| if (fastTest && typeof re === 'object') { | |
| // Avoids overriding in frozen environments | |
| Reflect.defineProperty(re, 'test', { value: fastTest }); | |
| } | |
| return re; | |
| } | |
| makeRe() { | |
| if (this.regexp || this.regexp === false) | |
| return this.regexp; | |
| // at this point, this.set is a 2d array of partial | |
| // pattern strings, or "**". | |
| // | |
| // It's better to use .match(). This function shouldn't | |
| // be used, really, but it's pretty convenient sometimes, | |
| // when you just want to work with a regex. | |
| const set = this.set; | |
| if (!set.length) { | |
| this.regexp = false; | |
| return this.regexp; | |
| } | |
| const options = this.options; | |
| const twoStar = options.noglobstar | |
| ? star | |
| : options.dot | |
| ? twoStarDot | |
| : twoStarNoDot; | |
| const flags = new Set(options.nocase ? ['i'] : []); | |
| // regexpify non-globstar patterns | |
| // if ** is only item, then we just do one twoStar | |
| // if ** is first, and there are more, prepend (\/|twoStar\/)? to next | |
| // if ** is last, append (\/twoStar|) to previous | |
| // if ** is in the middle, append (\/|\/twoStar\/) to previous | |
| // then filter out GLOBSTAR symbols | |
| let re = set | |
| .map(pattern => { | |
| const pp = pattern.map(p => { | |
| if (p instanceof RegExp) { | |
| for (const f of p.flags.split('')) | |
| flags.add(f); | |
| } | |
| return typeof p === 'string' | |
| ? regExpEscape(p) | |
| : p === exports.GLOBSTAR | |
| ? exports.GLOBSTAR | |
| : p._src; | |
| }); | |
| pp.forEach((p, i) => { | |
| const next = pp[i + 1]; | |
| const prev = pp[i - 1]; | |
| if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) { | |
| return; | |
| } | |
| if (prev === undefined) { | |
| if (next !== undefined && next !== exports.GLOBSTAR) { | |
| pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next; | |
| } | |
| else { | |
| pp[i] = twoStar; | |
| } | |
| } | |
| else if (next === undefined) { | |
| pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?'; | |
| } | |
| else if (next !== exports.GLOBSTAR) { | |
| pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next; | |
| pp[i + 1] = exports.GLOBSTAR; | |
| } | |
| }); | |
| return pp.filter(p => p !== exports.GLOBSTAR).join('/'); | |
| }) | |
| .join('|'); | |
| // need to wrap in parens if we had more than one thing with |, | |
| // otherwise only the first will be anchored to ^ and the last to $ | |
| const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', '']; | |
| // must match entire pattern | |
| // ending in a * or ** will make it less strict. | |
| re = '^' + open + re + close + '$'; | |
| // can match anything, as long as it's not this. | |
| if (this.negate) | |
| re = '^(?!' + re + ').+$'; | |
| try { | |
| this.regexp = new RegExp(re, [...flags].join('')); | |
| /* c8 ignore start */ | |
| } | |
| catch (ex) { | |
| // should be impossible | |
| this.regexp = false; | |
| } | |
| /* c8 ignore stop */ | |
| return this.regexp; | |
| } | |
| slashSplit(p) { | |
| // if p starts with // on windows, we preserve that | |
| // so that UNC paths aren't broken. Otherwise, any number of | |
| // / characters are coalesced into one, unless | |
| // preserveMultipleSlashes is set to true. | |
| if (this.preserveMultipleSlashes) { | |
| return p.split('/'); | |
| } | |
| else if (this.isWindows && /^\/\/[^\/]+/.test(p)) { | |
| // add an extra '' for the one we lose | |
| return ['', ...p.split(/\/+/)]; | |
| } | |
| else { | |
| return p.split(/\/+/); | |
| } | |
| } | |
| match(f, partial = this.partial) { | |
| this.debug('match', f, this.pattern); | |
| // short-circuit in the case of busted things. | |
| // comments, etc. | |
| if (this.comment) { | |
| return false; | |
| } | |
| if (this.empty) { | |
| return f === ''; | |
| } | |
| if (f === '/' && partial) { | |
| return true; | |
| } | |
| const options = this.options; | |
| // windows: need to use /, not \ | |
| if (this.isWindows) { | |
| f = f.split('\\').join('/'); | |
| } | |
| // treat the test path as a set of pathparts. | |
| const ff = this.slashSplit(f); | |
| this.debug(this.pattern, 'split', ff); | |
| // just ONE of the pattern sets in this.set needs to match | |
| // in order for it to be valid. If negating, then just one | |
| // match means that we have failed. | |
| // Either way, return on the first hit. | |
| const set = this.set; | |
| this.debug(this.pattern, 'set', set); | |
| // Find the basename of the path by looking for the last non-empty segment | |
| let filename = ff[ff.length - 1]; | |
| if (!filename) { | |
| for (let i = ff.length - 2; !filename && i >= 0; i--) { | |
| filename = ff[i]; | |
| } | |
| } | |
| for (let i = 0; i < set.length; i++) { | |
| const pattern = set[i]; | |
| let file = ff; | |
| if (options.matchBase && pattern.length === 1) { | |
| file = [filename]; | |
| } | |
| const hit = this.matchOne(file, pattern, partial); | |
| if (hit) { | |
| if (options.flipNegate) { | |
| return true; | |
| } | |
| return !this.negate; | |
| } | |
| } | |
| // didn't get any hits. this is success if it's a negative | |
| // pattern, failure otherwise. | |
| if (options.flipNegate) { | |
| return false; | |
| } | |
| return this.negate; | |
| } | |
| static defaults(def) { | |
| return exports.minimatch.defaults(def).Minimatch; | |
| } | |
| } | |
| exports.Minimatch = Minimatch; | |
| /* c8 ignore start */ | |
| var ast_js_2 = require("./ast.js"); | |
| Object.defineProperty(exports, "AST", { enumerable: true, get: function () { return ast_js_2.AST; } }); | |
| var escape_js_2 = require("./escape.js"); | |
| Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } }); | |
| var unescape_js_2 = require("./unescape.js"); | |
| Object.defineProperty(exports, "unescape", { enumerable: true, get: function () { return unescape_js_2.unescape; } }); | |
| /* c8 ignore stop */ | |
| exports.minimatch.AST = ast_js_1.AST; | |
| exports.minimatch.Minimatch = Minimatch; | |
| exports.minimatch.escape = escape_js_1.escape; | |
| exports.minimatch.unescape = unescape_js_1.unescape; | |
| //# sourceMappingURL=index.js.map |
Xet Storage Details
- Size:
- 39.9 kB
- Xet hash:
- af5b5fc6ba6e875be062eb02fd00492065cb96af664ae7184a50c3887fba6d61
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.