source: node_modules/minimatch/dist/commonjs/index.js@ 62b2964

finki-main main
Last change on this file since 62b2964 was 81bc7da, checked in by Klimentina Efremova <klimentina08642@…>, 3 months ago

Initial commit

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