c25dbd3cd6b9d8c1cd8a32e00c70656b68914f353896dabea00b4382f3415e783ab626e7be6b279af565a2b8c5737bd69a4f6f7a87ed728cc021fdfe775bc4 39 KB

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