index.js 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.unescape = exports.escape = exports.Minimatch = exports.match = exports.makeRe = exports.braceExpand = exports.defaults = exports.filter = exports.GLOBSTAR = exports.sep = exports.minimatch = void 0;
  7. const brace_expansion_1 = __importDefault(require("brace-expansion"));
  8. const brace_expressions_js_1 = require("./brace-expressions.js");
  9. const escape_js_1 = require("./escape.js");
  10. const unescape_js_1 = require("./unescape.js");
  11. const minimatch = (p, pattern, options = {}) => {
  12. assertValidPattern(pattern);
  13. // shortcut: comments match nothing.
  14. if (!options.nocomment && pattern.charAt(0) === '#') {
  15. return false;
  16. }
  17. return new Minimatch(pattern, options).match(p);
  18. };
  19. exports.minimatch = minimatch;
  20. exports.default = exports.minimatch;
  21. // Optimized checking for the most common glob patterns.
  22. const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
  23. const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
  24. const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
  25. const starDotExtTestNocase = (ext) => {
  26. ext = ext.toLowerCase();
  27. return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
  28. };
  29. const starDotExtTestNocaseDot = (ext) => {
  30. ext = ext.toLowerCase();
  31. return (f) => f.toLowerCase().endsWith(ext);
  32. };
  33. const starDotStarRE = /^\*+\.\*+$/;
  34. const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
  35. const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
  36. const dotStarRE = /^\.\*+$/;
  37. const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
  38. const starRE = /^\*+$/;
  39. const starTest = (f) => f.length !== 0 && !f.startsWith('.');
  40. const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
  41. const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
  42. const qmarksTestNocase = ([$0, ext = '']) => {
  43. const noext = qmarksTestNoExt([$0]);
  44. if (!ext)
  45. return noext;
  46. ext = ext.toLowerCase();
  47. return (f) => noext(f) && f.toLowerCase().endsWith(ext);
  48. };
  49. const qmarksTestNocaseDot = ([$0, ext = '']) => {
  50. const noext = qmarksTestNoExtDot([$0]);
  51. if (!ext)
  52. return noext;
  53. ext = ext.toLowerCase();
  54. return (f) => noext(f) && f.toLowerCase().endsWith(ext);
  55. };
  56. const qmarksTestDot = ([$0, ext = '']) => {
  57. const noext = qmarksTestNoExtDot([$0]);
  58. return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
  59. };
  60. const qmarksTest = ([$0, ext = '']) => {
  61. const noext = qmarksTestNoExt([$0]);
  62. return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
  63. };
  64. const qmarksTestNoExt = ([$0]) => {
  65. const len = $0.length;
  66. return (f) => f.length === len && !f.startsWith('.');
  67. };
  68. const qmarksTestNoExtDot = ([$0]) => {
  69. const len = $0.length;
  70. return (f) => f.length === len && f !== '.' && f !== '..';
  71. };
  72. /* c8 ignore start */
  73. const defaultPlatform = (typeof process === 'object' && process
  74. ? (typeof process.env === 'object' &&
  75. process.env &&
  76. process.env.__MINIMATCH_TESTING_PLATFORM__) ||
  77. process.platform
  78. : 'posix');
  79. const path = {
  80. win32: { sep: '\\' },
  81. posix: { sep: '/' },
  82. };
  83. /* c8 ignore stop */
  84. exports.sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep;
  85. exports.minimatch.sep = exports.sep;
  86. exports.GLOBSTAR = Symbol('globstar **');
  87. exports.minimatch.GLOBSTAR = exports.GLOBSTAR;
  88. const plTypes = {
  89. '!': { open: '(?:(?!(?:', close: '))[^/]*?)' },
  90. '?': { open: '(?:', close: ')?' },
  91. '+': { open: '(?:', close: ')+' },
  92. '*': { open: '(?:', close: ')*' },
  93. '@': { open: '(?:', close: ')' },
  94. };
  95. // any single thing other than /
  96. // don't need to escape / when using new RegExp()
  97. const qmark = '[^/]';
  98. // * => any number of characters
  99. const star = qmark + '*?';
  100. // ** when dots are allowed. Anything goes, except .. and .
  101. // not (^ or / followed by one or two dots followed by $ or /),
  102. // followed by anything, any number of times.
  103. const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
  104. // not a ^ or / followed by a dot,
  105. // followed by anything, any number of times.
  106. const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
  107. // "abc" -> { a:true, b:true, c:true }
  108. const charSet = (s) => s.split('').reduce((set, c) => {
  109. set[c] = true;
  110. return set;
  111. }, {});
  112. // characters that need to be escaped in RegExp.
  113. const reSpecials = charSet('().*{}+?[]^$\\!');
  114. // characters that indicate we have to add the pattern start
  115. const addPatternStartSet = charSet('[.(');
  116. const filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options);
  117. exports.filter = filter;
  118. exports.minimatch.filter = exports.filter;
  119. const ext = (a, b = {}) => Object.assign({}, a, b);
  120. const defaults = (def) => {
  121. if (!def || typeof def !== 'object' || !Object.keys(def).length) {
  122. return exports.minimatch;
  123. }
  124. const orig = exports.minimatch;
  125. const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
  126. return Object.assign(m, {
  127. Minimatch: class Minimatch extends orig.Minimatch {
  128. constructor(pattern, options = {}) {
  129. super(pattern, ext(def, options));
  130. }
  131. static defaults(options) {
  132. return orig.defaults(ext(def, options)).Minimatch;
  133. }
  134. },
  135. unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
  136. escape: (s, options = {}) => orig.escape(s, ext(def, options)),
  137. filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
  138. defaults: (options) => orig.defaults(ext(def, options)),
  139. makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
  140. braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
  141. match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
  142. sep: orig.sep,
  143. GLOBSTAR: exports.GLOBSTAR,
  144. });
  145. };
  146. exports.defaults = defaults;
  147. exports.minimatch.defaults = exports.defaults;
  148. // Brace expansion:
  149. // a{b,c}d -> abd acd
  150. // a{b,}c -> abc ac
  151. // a{0..3}d -> a0d a1d a2d a3d
  152. // a{b,c{d,e}f}g -> abg acdfg acefg
  153. // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
  154. //
  155. // Invalid sets are not expanded.
  156. // a{2..}b -> a{2..}b
  157. // a{b}c -> a{b}c
  158. const braceExpand = (pattern, options = {}) => {
  159. assertValidPattern(pattern);
  160. // Thanks to Yeting Li <https://github.com/yetingli> for
  161. // improving this regexp to avoid a ReDOS vulnerability.
  162. if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
  163. // shortcut. no need to expand.
  164. return [pattern];
  165. }
  166. return (0, brace_expansion_1.default)(pattern);
  167. };
  168. exports.braceExpand = braceExpand;
  169. exports.minimatch.braceExpand = exports.braceExpand;
  170. const MAX_PATTERN_LENGTH = 1024 * 64;
  171. const assertValidPattern = (pattern) => {
  172. if (typeof pattern !== 'string') {
  173. throw new TypeError('invalid pattern');
  174. }
  175. if (pattern.length > MAX_PATTERN_LENGTH) {
  176. throw new TypeError('pattern is too long');
  177. }
  178. };
  179. // parse a component of the expanded set.
  180. // At this point, no pattern may contain "/" in it
  181. // so we're going to return a 2d array, where each entry is the full
  182. // pattern, split on '/', and then turned into a regular expression.
  183. // A regexp is made at the end which joins each array with an
  184. // escaped /, and another full one which joins each regexp with |.
  185. //
  186. // Following the lead of Bash 4.1, note that "**" only has special meaning
  187. // when it is the *only* thing in a path portion. Otherwise, any series
  188. // of * is equivalent to a single *. Globstar behavior is enabled by
  189. // default, and can be disabled by setting options.noglobstar.
  190. const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
  191. exports.makeRe = makeRe;
  192. exports.minimatch.makeRe = exports.makeRe;
  193. const match = (list, pattern, options = {}) => {
  194. const mm = new Minimatch(pattern, options);
  195. list = list.filter(f => mm.match(f));
  196. if (mm.options.nonull && !list.length) {
  197. list.push(pattern);
  198. }
  199. return list;
  200. };
  201. exports.match = match;
  202. exports.minimatch.match = exports.match;
  203. // replace stuff like \* with *
  204. const globUnescape = (s) => s.replace(/\\(.)/g, '$1');
  205. const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
  206. const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
  207. class Minimatch {
  208. options;
  209. set;
  210. pattern;
  211. windowsPathsNoEscape;
  212. nonegate;
  213. negate;
  214. comment;
  215. empty;
  216. preserveMultipleSlashes;
  217. partial;
  218. globSet;
  219. globParts;
  220. nocase;
  221. isWindows;
  222. platform;
  223. windowsNoMagicRoot;
  224. regexp;
  225. constructor(pattern, options = {}) {
  226. assertValidPattern(pattern);
  227. options = options || {};
  228. this.options = options;
  229. this.pattern = pattern;
  230. this.platform = options.platform || defaultPlatform;
  231. this.isWindows = this.platform === 'win32';
  232. this.windowsPathsNoEscape =
  233. !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
  234. if (this.windowsPathsNoEscape) {
  235. this.pattern = this.pattern.replace(/\\/g, '/');
  236. }
  237. this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
  238. this.regexp = null;
  239. this.negate = false;
  240. this.nonegate = !!options.nonegate;
  241. this.comment = false;
  242. this.empty = false;
  243. this.partial = !!options.partial;
  244. this.nocase = !!this.options.nocase;
  245. this.windowsNoMagicRoot =
  246. options.windowsNoMagicRoot !== undefined
  247. ? options.windowsNoMagicRoot
  248. : !!(this.isWindows && this.nocase);
  249. this.globSet = [];
  250. this.globParts = [];
  251. this.set = [];
  252. // make the set of regexps etc.
  253. this.make();
  254. }
  255. hasMagic() {
  256. if (this.options.magicalBraces && this.set.length > 1) {
  257. return true;
  258. }
  259. for (const pattern of this.set) {
  260. for (const part of pattern) {
  261. if (typeof part !== 'string')
  262. return true;
  263. }
  264. }
  265. return false;
  266. }
  267. debug(..._) { }
  268. make() {
  269. const pattern = this.pattern;
  270. const options = this.options;
  271. // empty patterns and comments match nothing.
  272. if (!options.nocomment && pattern.charAt(0) === '#') {
  273. this.comment = true;
  274. return;
  275. }
  276. if (!pattern) {
  277. this.empty = true;
  278. return;
  279. }
  280. // step 1: figure out negation, etc.
  281. this.parseNegate();
  282. // step 2: expand braces
  283. this.globSet = [...new Set(this.braceExpand())];
  284. if (options.debug) {
  285. this.debug = (...args) => console.error(...args);
  286. }
  287. this.debug(this.pattern, this.globSet);
  288. // step 3: now we have a set, so turn each one into a series of
  289. // path-portion matching patterns.
  290. // These will be regexps, except in the case of "**", which is
  291. // set to the GLOBSTAR object for globstar behavior,
  292. // and will not contain any / characters
  293. //
  294. // First, we preprocess to make the glob pattern sets a bit simpler
  295. // and deduped. There are some perf-killing patterns that can cause
  296. // problems with a glob walk, but we can simplify them down a bit.
  297. const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
  298. this.globParts = this.preprocess(rawGlobParts);
  299. this.debug(this.pattern, this.globParts);
  300. // glob --> regexps
  301. let set = this.globParts.map((s, _, __) => {
  302. if (this.isWindows && this.windowsNoMagicRoot) {
  303. // check if it's a drive or unc path.
  304. const isUNC = s[0] === '' &&
  305. s[1] === '' &&
  306. (s[2] === '?' || !globMagic.test(s[2])) &&
  307. !globMagic.test(s[3]);
  308. const isDrive = /^[a-z]:/i.test(s[0]);
  309. if (isUNC) {
  310. return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))];
  311. }
  312. else if (isDrive) {
  313. return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
  314. }
  315. }
  316. return s.map(ss => this.parse(ss));
  317. });
  318. this.debug(this.pattern, set);
  319. // filter out everything that didn't compile properly.
  320. this.set = set.filter(s => s.indexOf(false) === -1);
  321. // do not treat the ? in UNC paths as magic
  322. if (this.isWindows) {
  323. for (let i = 0; i < this.set.length; i++) {
  324. const p = this.set[i];
  325. if (p[0] === '' &&
  326. p[1] === '' &&
  327. this.globParts[i][2] === '?' &&
  328. typeof p[3] === 'string' &&
  329. /^[a-z]:$/i.test(p[3])) {
  330. p[2] = '?';
  331. }
  332. }
  333. }
  334. this.debug(this.pattern, this.set);
  335. }
  336. // various transforms to equivalent pattern sets that are
  337. // faster to process in a filesystem walk. The goal is to
  338. // eliminate what we can, and push all ** patterns as far
  339. // to the right as possible, even if it increases the number
  340. // of patterns that we have to process.
  341. preprocess(globParts) {
  342. // if we're not in globstar mode, then turn all ** into *
  343. if (this.options.noglobstar) {
  344. for (let i = 0; i < globParts.length; i++) {
  345. for (let j = 0; j < globParts[i].length; j++) {
  346. if (globParts[i][j] === '**') {
  347. globParts[i][j] = '*';
  348. }
  349. }
  350. }
  351. }
  352. const { optimizationLevel = 1 } = this.options;
  353. if (optimizationLevel >= 2) {
  354. // aggressive optimization for the purpose of fs walking
  355. globParts = this.firstPhasePreProcess(globParts);
  356. globParts = this.secondPhasePreProcess(globParts);
  357. }
  358. else if (optimizationLevel >= 1) {
  359. // just basic optimizations to remove some .. parts
  360. globParts = this.levelOneOptimize(globParts);
  361. }
  362. else {
  363. globParts = this.adjascentGlobstarOptimize(globParts);
  364. }
  365. return globParts;
  366. }
  367. // just get rid of adjascent ** portions
  368. adjascentGlobstarOptimize(globParts) {
  369. return globParts.map(parts => {
  370. let gs = -1;
  371. while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
  372. let i = gs;
  373. while (parts[i + 1] === '**') {
  374. i++;
  375. }
  376. if (i !== gs) {
  377. parts.splice(gs, i - gs);
  378. }
  379. }
  380. return parts;
  381. });
  382. }
  383. // get rid of adjascent ** and resolve .. portions
  384. levelOneOptimize(globParts) {
  385. return globParts.map(parts => {
  386. parts = parts.reduce((set, part) => {
  387. const prev = set[set.length - 1];
  388. if (part === '**' && prev === '**') {
  389. return set;
  390. }
  391. if (part === '..') {
  392. if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
  393. set.pop();
  394. return set;
  395. }
  396. }
  397. set.push(part);
  398. return set;
  399. }, []);
  400. return parts.length === 0 ? [''] : parts;
  401. });
  402. }
  403. levelTwoFileOptimize(parts) {
  404. if (!Array.isArray(parts)) {
  405. parts = this.slashSplit(parts);
  406. }
  407. let didSomething = false;
  408. do {
  409. didSomething = false;
  410. // <pre>/<e>/<rest> -> <pre>/<rest>
  411. if (!this.preserveMultipleSlashes) {
  412. for (let i = 1; i < parts.length - 1; i++) {
  413. const p = parts[i];
  414. // don't squeeze out UNC patterns
  415. if (i === 1 && p === '' && parts[0] === '')
  416. continue;
  417. if (p === '.' || p === '') {
  418. didSomething = true;
  419. parts.splice(i, 1);
  420. i--;
  421. }
  422. }
  423. if (parts[0] === '.' &&
  424. parts.length === 2 &&
  425. (parts[1] === '.' || parts[1] === '')) {
  426. didSomething = true;
  427. parts.pop();
  428. }
  429. }
  430. // <pre>/<p>/../<rest> -> <pre>/<rest>
  431. let dd = 0;
  432. while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
  433. const p = parts[dd - 1];
  434. if (p && p !== '.' && p !== '..' && p !== '**') {
  435. didSomething = true;
  436. parts.splice(dd - 1, 2);
  437. dd -= 2;
  438. }
  439. }
  440. } while (didSomething);
  441. return parts.length === 0 ? [''] : parts;
  442. }
  443. // First phase: single-pattern processing
  444. // <pre> is 1 or more portions
  445. // <rest> is 1 or more portions
  446. // <p> is any portion other than ., .., '', or **
  447. // <e> is . or ''
  448. //
  449. // **/.. is *brutal* for filesystem walking performance, because
  450. // it effectively resets the recursive walk each time it occurs,
  451. // and ** cannot be reduced out by a .. pattern part like a regexp
  452. // or most strings (other than .., ., and '') can be.
  453. //
  454. // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
  455. // <pre>/<e>/<rest> -> <pre>/<rest>
  456. // <pre>/<p>/../<rest> -> <pre>/<rest>
  457. // **/**/<rest> -> **/<rest>
  458. //
  459. // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
  460. // this WOULD be allowed if ** did follow symlinks, or * didn't
  461. firstPhasePreProcess(globParts) {
  462. let didSomething = false;
  463. do {
  464. didSomething = false;
  465. // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
  466. for (let parts of globParts) {
  467. let gs = -1;
  468. while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
  469. let gss = gs;
  470. while (parts[gss + 1] === '**') {
  471. // <pre>/**/**/<rest> -> <pre>/**/<rest>
  472. gss++;
  473. }
  474. // eg, if gs is 2 and gss is 4, that means we have 3 **
  475. // parts, and can remove 2 of them.
  476. if (gss > gs) {
  477. parts.splice(gs + 1, gss - gs);
  478. }
  479. let next = parts[gs + 1];
  480. const p = parts[gs + 2];
  481. const p2 = parts[gs + 3];
  482. if (next !== '..')
  483. continue;
  484. if (!p ||
  485. p === '.' ||
  486. p === '..' ||
  487. !p2 ||
  488. p2 === '.' ||
  489. p2 === '..') {
  490. continue;
  491. }
  492. didSomething = true;
  493. // edit parts in place, and push the new one
  494. parts.splice(gs, 1);
  495. const other = parts.slice(0);
  496. other[gs] = '**';
  497. globParts.push(other);
  498. gs--;
  499. }
  500. // <pre>/<e>/<rest> -> <pre>/<rest>
  501. if (!this.preserveMultipleSlashes) {
  502. for (let i = 1; i < parts.length - 1; i++) {
  503. const p = parts[i];
  504. // don't squeeze out UNC patterns
  505. if (i === 1 && p === '' && parts[0] === '')
  506. continue;
  507. if (p === '.' || p === '') {
  508. didSomething = true;
  509. parts.splice(i, 1);
  510. i--;
  511. }
  512. }
  513. if (parts[0] === '.' &&
  514. parts.length === 2 &&
  515. (parts[1] === '.' || parts[1] === '')) {
  516. didSomething = true;
  517. parts.pop();
  518. }
  519. }
  520. // <pre>/<p>/../<rest> -> <pre>/<rest>
  521. let dd = 0;
  522. while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
  523. const p = parts[dd - 1];
  524. if (p && p !== '.' && p !== '..' && p !== '**') {
  525. didSomething = true;
  526. const needDot = dd === 1 && parts[dd + 1] === '**';
  527. const splin = needDot ? ['.'] : [];
  528. parts.splice(dd - 1, 2, ...splin);
  529. if (parts.length === 0)
  530. parts.push('');
  531. dd -= 2;
  532. }
  533. }
  534. }
  535. } while (didSomething);
  536. return globParts;
  537. }
  538. // second phase: multi-pattern dedupes
  539. // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
  540. // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
  541. // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
  542. //
  543. // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
  544. // ^-- not valid because ** doens't follow symlinks
  545. secondPhasePreProcess(globParts) {
  546. for (let i = 0; i < globParts.length - 1; i++) {
  547. for (let j = i + 1; j < globParts.length; j++) {
  548. const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
  549. if (!matched)
  550. continue;
  551. globParts[i] = matched;
  552. globParts[j] = [];
  553. }
  554. }
  555. return globParts.filter(gs => gs.length);
  556. }
  557. partsMatch(a, b, emptyGSMatch = false) {
  558. let ai = 0;
  559. let bi = 0;
  560. let result = [];
  561. let which = '';
  562. while (ai < a.length && bi < b.length) {
  563. if (a[ai] === b[bi]) {
  564. result.push(which === 'b' ? b[bi] : a[ai]);
  565. ai++;
  566. bi++;
  567. }
  568. else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
  569. result.push(a[ai]);
  570. ai++;
  571. }
  572. else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
  573. result.push(b[bi]);
  574. bi++;
  575. }
  576. else if (a[ai] === '*' &&
  577. b[bi] &&
  578. (this.options.dot || !b[bi].startsWith('.')) &&
  579. b[bi] !== '**') {
  580. if (which === 'b')
  581. return false;
  582. which = 'a';
  583. result.push(a[ai]);
  584. ai++;
  585. bi++;
  586. }
  587. else if (b[bi] === '*' &&
  588. a[ai] &&
  589. (this.options.dot || !a[ai].startsWith('.')) &&
  590. a[ai] !== '**') {
  591. if (which === 'a')
  592. return false;
  593. which = 'b';
  594. result.push(b[bi]);
  595. ai++;
  596. bi++;
  597. }
  598. else {
  599. return false;
  600. }
  601. }
  602. // if we fall out of the loop, it means they two are identical
  603. // as long as their lengths match
  604. return a.length === b.length && result;
  605. }
  606. parseNegate() {
  607. if (this.nonegate)
  608. return;
  609. const pattern = this.pattern;
  610. let negate = false;
  611. let negateOffset = 0;
  612. for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
  613. negate = !negate;
  614. negateOffset++;
  615. }
  616. if (negateOffset)
  617. this.pattern = pattern.slice(negateOffset);
  618. this.negate = negate;
  619. }
  620. // set partial to true to test if, for example,
  621. // "/a/b" matches the start of "/*/b/*/d"
  622. // Partial means, if you run out of file before you run
  623. // out of pattern, then that's fine, as long as all
  624. // the parts match.
  625. matchOne(file, pattern, partial = false) {
  626. const options = this.options;
  627. // a UNC pattern like //?/c:/* can match a path like c:/x
  628. // and vice versa
  629. if (this.isWindows) {
  630. const fileUNC = file[0] === '' &&
  631. file[1] === '' &&
  632. file[2] === '?' &&
  633. typeof file[3] === 'string' &&
  634. /^[a-z]:$/i.test(file[3]);
  635. const patternUNC = pattern[0] === '' &&
  636. pattern[1] === '' &&
  637. pattern[2] === '?' &&
  638. typeof pattern[3] === 'string' &&
  639. /^[a-z]:$/i.test(pattern[3]);
  640. if (fileUNC && patternUNC) {
  641. const fd = file[3];
  642. const pd = pattern[3];
  643. if (fd.toLowerCase() === pd.toLowerCase()) {
  644. file[3] = pd;
  645. }
  646. }
  647. else if (patternUNC && typeof file[0] === 'string') {
  648. const pd = pattern[3];
  649. const fd = file[0];
  650. if (pd.toLowerCase() === fd.toLowerCase()) {
  651. pattern[3] = fd;
  652. pattern = pattern.slice(3);
  653. }
  654. }
  655. else if (fileUNC && typeof pattern[0] === 'string') {
  656. const fd = file[3];
  657. if (fd.toLowerCase() === pattern[0].toLowerCase()) {
  658. pattern[0] = fd;
  659. file = file.slice(3);
  660. }
  661. }
  662. }
  663. // resolve and reduce . and .. portions in the file as well.
  664. // dont' need to do the second phase, because it's only one string[]
  665. const { optimizationLevel = 1 } = this.options;
  666. if (optimizationLevel >= 2) {
  667. file = this.levelTwoFileOptimize(file);
  668. }
  669. this.debug('matchOne', this, { file, pattern });
  670. this.debug('matchOne', file.length, pattern.length);
  671. for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
  672. this.debug('matchOne loop');
  673. var p = pattern[pi];
  674. var f = file[fi];
  675. this.debug(pattern, p, f);
  676. // should be impossible.
  677. // some invalid regexp stuff in the set.
  678. /* c8 ignore start */
  679. if (p === false) {
  680. return false;
  681. }
  682. /* c8 ignore stop */
  683. if (p === exports.GLOBSTAR) {
  684. this.debug('GLOBSTAR', [pattern, p, f]);
  685. // "**"
  686. // a/**/b/**/c would match the following:
  687. // a/b/x/y/z/c
  688. // a/x/y/z/b/c
  689. // a/b/x/b/x/c
  690. // a/b/c
  691. // To do this, take the rest of the pattern after
  692. // the **, and see if it would match the file remainder.
  693. // If so, return success.
  694. // If not, the ** "swallows" a segment, and try again.
  695. // This is recursively awful.
  696. //
  697. // a/**/b/**/c matching a/b/x/y/z/c
  698. // - a matches a
  699. // - doublestar
  700. // - matchOne(b/x/y/z/c, b/**/c)
  701. // - b matches b
  702. // - doublestar
  703. // - matchOne(x/y/z/c, c) -> no
  704. // - matchOne(y/z/c, c) -> no
  705. // - matchOne(z/c, c) -> no
  706. // - matchOne(c, c) yes, hit
  707. var fr = fi;
  708. var pr = pi + 1;
  709. if (pr === pl) {
  710. this.debug('** at the end');
  711. // a ** at the end will just swallow the rest.
  712. // We have found a match.
  713. // however, it will not swallow /.x, unless
  714. // options.dot is set.
  715. // . and .. are *never* matched by **, for explosively
  716. // exponential reasons.
  717. for (; fi < fl; fi++) {
  718. if (file[fi] === '.' ||
  719. file[fi] === '..' ||
  720. (!options.dot && file[fi].charAt(0) === '.'))
  721. return false;
  722. }
  723. return true;
  724. }
  725. // ok, let's see if we can swallow whatever we can.
  726. while (fr < fl) {
  727. var swallowee = file[fr];
  728. this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
  729. // XXX remove this slice. Just pass the start index.
  730. if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
  731. this.debug('globstar found match!', fr, fl, swallowee);
  732. // found a match.
  733. return true;
  734. }
  735. else {
  736. // can't swallow "." or ".." ever.
  737. // can only swallow ".foo" when explicitly asked.
  738. if (swallowee === '.' ||
  739. swallowee === '..' ||
  740. (!options.dot && swallowee.charAt(0) === '.')) {
  741. this.debug('dot detected!', file, fr, pattern, pr);
  742. break;
  743. }
  744. // ** swallows a segment, and continue.
  745. this.debug('globstar swallow a segment, and continue');
  746. fr++;
  747. }
  748. }
  749. // no match was found.
  750. // However, in partial mode, we can't say this is necessarily over.
  751. /* c8 ignore start */
  752. if (partial) {
  753. // ran out of file
  754. this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
  755. if (fr === fl) {
  756. return true;
  757. }
  758. }
  759. /* c8 ignore stop */
  760. return false;
  761. }
  762. // something other than **
  763. // non-magic patterns just have to match exactly
  764. // patterns with magic have been turned into regexps.
  765. let hit;
  766. if (typeof p === 'string') {
  767. hit = f === p;
  768. this.debug('string match', p, f, hit);
  769. }
  770. else {
  771. hit = p.test(f);
  772. this.debug('pattern match', p, f, hit);
  773. }
  774. if (!hit)
  775. return false;
  776. }
  777. // Note: ending in / means that we'll get a final ""
  778. // at the end of the pattern. This can only match a
  779. // corresponding "" at the end of the file.
  780. // If the file ends in /, then it can only match a
  781. // a pattern that ends in /, unless the pattern just
  782. // doesn't have any more for it. But, a/b/ should *not*
  783. // match "a/b/*", even though "" matches against the
  784. // [^/]*? pattern, except in partial mode, where it might
  785. // simply not be reached yet.
  786. // However, a/b/ should still satisfy a/*
  787. // now either we fell off the end of the pattern, or we're done.
  788. if (fi === fl && pi === pl) {
  789. // ran out of pattern and filename at the same time.
  790. // an exact hit!
  791. return true;
  792. }
  793. else if (fi === fl) {
  794. // ran out of file, but still had pattern left.
  795. // this is ok if we're doing the match as part of
  796. // a glob fs traversal.
  797. return partial;
  798. }
  799. else if (pi === pl) {
  800. // ran out of pattern, still have file left.
  801. // this is only acceptable if we're on the very last
  802. // empty segment of a file with a trailing slash.
  803. // a/* should match a/b/
  804. return fi === fl - 1 && file[fi] === '';
  805. /* c8 ignore start */
  806. }
  807. else {
  808. // should be unreachable.
  809. throw new Error('wtf?');
  810. }
  811. /* c8 ignore stop */
  812. }
  813. braceExpand() {
  814. return (0, exports.braceExpand)(this.pattern, this.options);
  815. }
  816. parse(pattern) {
  817. assertValidPattern(pattern);
  818. const options = this.options;
  819. // shortcuts
  820. if (pattern === '**')
  821. return exports.GLOBSTAR;
  822. if (pattern === '')
  823. return '';
  824. // far and away, the most common glob pattern parts are
  825. // *, *.*, and *.<ext> Add a fast check method for those.
  826. let m;
  827. let fastTest = null;
  828. if ((m = pattern.match(starRE))) {
  829. fastTest = options.dot ? starTestDot : starTest;
  830. }
  831. else if ((m = pattern.match(starDotExtRE))) {
  832. fastTest = (options.nocase
  833. ? options.dot
  834. ? starDotExtTestNocaseDot
  835. : starDotExtTestNocase
  836. : options.dot
  837. ? starDotExtTestDot
  838. : starDotExtTest)(m[1]);
  839. }
  840. else if ((m = pattern.match(qmarksRE))) {
  841. fastTest = (options.nocase
  842. ? options.dot
  843. ? qmarksTestNocaseDot
  844. : qmarksTestNocase
  845. : options.dot
  846. ? qmarksTestDot
  847. : qmarksTest)(m);
  848. }
  849. else if ((m = pattern.match(starDotStarRE))) {
  850. fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
  851. }
  852. else if ((m = pattern.match(dotStarRE))) {
  853. fastTest = dotStarTest;
  854. }
  855. let re = '';
  856. let hasMagic = false;
  857. let escaping = false;
  858. // ? => one single character
  859. const patternListStack = [];
  860. const negativeLists = [];
  861. let stateChar = false;
  862. let uflag = false;
  863. let pl;
  864. // . and .. never match anything that doesn't start with .,
  865. // even when options.dot is set. However, if the pattern
  866. // starts with ., then traversal patterns can match.
  867. let dotTravAllowed = pattern.charAt(0) === '.';
  868. let dotFileAllowed = options.dot || dotTravAllowed;
  869. const patternStart = () => dotTravAllowed
  870. ? ''
  871. : dotFileAllowed
  872. ? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
  873. : '(?!\\.)';
  874. const subPatternStart = (p) => p.charAt(0) === '.'
  875. ? ''
  876. : options.dot
  877. ? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
  878. : '(?!\\.)';
  879. const clearStateChar = () => {
  880. if (stateChar) {
  881. // we had some state-tracking character
  882. // that wasn't consumed by this pass.
  883. switch (stateChar) {
  884. case '*':
  885. re += star;
  886. hasMagic = true;
  887. break;
  888. case '?':
  889. re += qmark;
  890. hasMagic = true;
  891. break;
  892. default:
  893. re += '\\' + stateChar;
  894. break;
  895. }
  896. this.debug('clearStateChar %j %j', stateChar, re);
  897. stateChar = false;
  898. }
  899. };
  900. for (let i = 0, c; i < pattern.length && (c = pattern.charAt(i)); i++) {
  901. this.debug('%s\t%s %s %j', pattern, i, re, c);
  902. // skip over any that are escaped.
  903. if (escaping) {
  904. // completely not allowed, even escaped.
  905. // should be impossible.
  906. /* c8 ignore start */
  907. if (c === '/') {
  908. return false;
  909. }
  910. /* c8 ignore stop */
  911. if (reSpecials[c]) {
  912. re += '\\';
  913. }
  914. re += c;
  915. escaping = false;
  916. continue;
  917. }
  918. switch (c) {
  919. // Should already be path-split by now.
  920. /* c8 ignore start */
  921. case '/': {
  922. return false;
  923. }
  924. /* c8 ignore stop */
  925. case '\\':
  926. clearStateChar();
  927. escaping = true;
  928. continue;
  929. // the various stateChar values
  930. // for the "extglob" stuff.
  931. case '?':
  932. case '*':
  933. case '+':
  934. case '@':
  935. case '!':
  936. this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c);
  937. // if we already have a stateChar, then it means
  938. // that there was something like ** or +? in there.
  939. // Handle the stateChar, then proceed with this one.
  940. this.debug('call clearStateChar %j', stateChar);
  941. clearStateChar();
  942. stateChar = c;
  943. // if extglob is disabled, then +(asdf|foo) isn't a thing.
  944. // just clear the statechar *now*, rather than even diving into
  945. // the patternList stuff.
  946. if (options.noext)
  947. clearStateChar();
  948. continue;
  949. case '(': {
  950. if (!stateChar) {
  951. re += '\\(';
  952. continue;
  953. }
  954. const plEntry = {
  955. type: stateChar,
  956. start: i - 1,
  957. reStart: re.length,
  958. open: plTypes[stateChar].open,
  959. close: plTypes[stateChar].close,
  960. };
  961. this.debug(this.pattern, '\t', plEntry);
  962. patternListStack.push(plEntry);
  963. // negation is (?:(?!(?:js)(?:<rest>))[^/]*)
  964. re += plEntry.open;
  965. // next entry starts with a dot maybe?
  966. if (plEntry.start === 0 && plEntry.type !== '!') {
  967. dotTravAllowed = true;
  968. re += subPatternStart(pattern.slice(i + 1));
  969. }
  970. this.debug('plType %j %j', stateChar, re);
  971. stateChar = false;
  972. continue;
  973. }
  974. case ')': {
  975. const plEntry = patternListStack[patternListStack.length - 1];
  976. if (!plEntry) {
  977. re += '\\)';
  978. continue;
  979. }
  980. patternListStack.pop();
  981. // closing an extglob
  982. clearStateChar();
  983. hasMagic = true;
  984. pl = plEntry;
  985. // negation is (?:(?!js)[^/]*)
  986. // The others are (?:<pattern>)<type>
  987. re += pl.close;
  988. if (pl.type === '!') {
  989. negativeLists.push(Object.assign(pl, { reEnd: re.length }));
  990. }
  991. continue;
  992. }
  993. case '|': {
  994. const plEntry = patternListStack[patternListStack.length - 1];
  995. if (!plEntry) {
  996. re += '\\|';
  997. continue;
  998. }
  999. clearStateChar();
  1000. re += '|';
  1001. // next subpattern can start with a dot?
  1002. if (plEntry.start === 0 && plEntry.type !== '!') {
  1003. dotTravAllowed = true;
  1004. re += subPatternStart(pattern.slice(i + 1));
  1005. }
  1006. continue;
  1007. }
  1008. // these are mostly the same in regexp and glob
  1009. case '[':
  1010. // swallow any state-tracking char before the [
  1011. clearStateChar();
  1012. const [src, needUflag, consumed, magic] = (0, brace_expressions_js_1.parseClass)(pattern, i);
  1013. if (consumed) {
  1014. re += src;
  1015. uflag = uflag || needUflag;
  1016. i += consumed - 1;
  1017. hasMagic = hasMagic || magic;
  1018. }
  1019. else {
  1020. re += '\\[';
  1021. }
  1022. continue;
  1023. case ']':
  1024. re += '\\' + c;
  1025. continue;
  1026. default:
  1027. // swallow any state char that wasn't consumed
  1028. clearStateChar();
  1029. re += regExpEscape(c);
  1030. break;
  1031. } // switch
  1032. } // for
  1033. // handle the case where we had a +( thing at the *end*
  1034. // of the pattern.
  1035. // each pattern list stack adds 3 chars, and we need to go through
  1036. // and escape any | chars that were passed through as-is for the regexp.
  1037. // Go through and escape them, taking care not to double-escape any
  1038. // | chars that were already escaped.
  1039. for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
  1040. let tail;
  1041. tail = re.slice(pl.reStart + pl.open.length);
  1042. this.debug(this.pattern, 'setting tail', re, pl);
  1043. // maybe some even number of \, then maybe 1 \, followed by a |
  1044. tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
  1045. if (!$2) {
  1046. // the | isn't already escaped, so escape it.
  1047. $2 = '\\';
  1048. // should already be done
  1049. /* c8 ignore start */
  1050. }
  1051. /* c8 ignore stop */
  1052. // need to escape all those slashes *again*, without escaping the
  1053. // one that we need for escaping the | character. As it works out,
  1054. // escaping an even number of slashes can be done by simply repeating
  1055. // it exactly after itself. That's why this trick works.
  1056. //
  1057. // I am sorry that you have to see this.
  1058. return $1 + $1 + $2 + '|';
  1059. });
  1060. this.debug('tail=%j\n %s', tail, tail, pl, re);
  1061. const t = pl.type === '*' ? star : pl.type === '?' ? qmark : '\\' + pl.type;
  1062. hasMagic = true;
  1063. re = re.slice(0, pl.reStart) + t + '\\(' + tail;
  1064. }
  1065. // handle trailing things that only matter at the very end.
  1066. clearStateChar();
  1067. if (escaping) {
  1068. // trailing \\
  1069. re += '\\\\';
  1070. }
  1071. // only need to apply the nodot start if the re starts with
  1072. // something that could conceivably capture a dot
  1073. const addPatternStart = addPatternStartSet[re.charAt(0)];
  1074. // Hack to work around lack of negative lookbehind in JS
  1075. // A pattern like: *.!(x).!(y|z) needs to ensure that a name
  1076. // like 'a.xyz.yz' doesn't match. So, the first negative
  1077. // lookahead, has to look ALL the way ahead, to the end of
  1078. // the pattern.
  1079. for (let n = negativeLists.length - 1; n > -1; n--) {
  1080. const nl = negativeLists[n];
  1081. const nlBefore = re.slice(0, nl.reStart);
  1082. const nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
  1083. let nlAfter = re.slice(nl.reEnd);
  1084. const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter;
  1085. // Handle nested stuff like *(*.js|!(*.json)), where open parens
  1086. // mean that we should *not* include the ) in the bit that is considered
  1087. // "after" the negated section.
  1088. const closeParensBefore = nlBefore.split(')').length;
  1089. const openParensBefore = nlBefore.split('(').length - closeParensBefore;
  1090. let cleanAfter = nlAfter;
  1091. for (let i = 0; i < openParensBefore; i++) {
  1092. cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
  1093. }
  1094. nlAfter = cleanAfter;
  1095. const dollar = nlAfter === '' ? '(?:$|\\/)' : '';
  1096. re = nlBefore + nlFirst + nlAfter + dollar + nlLast;
  1097. }
  1098. // if the re is not "" at this point, then we need to make sure
  1099. // it doesn't match against an empty path part.
  1100. // Otherwise a/* will match a/, which it should not.
  1101. if (re !== '' && hasMagic) {
  1102. re = '(?=.)' + re;
  1103. }
  1104. if (addPatternStart) {
  1105. re = patternStart() + re;
  1106. }
  1107. // if it's nocase, and the lcase/uppercase don't match, it's magic
  1108. if (options.nocase && !hasMagic && !options.nocaseMagicOnly) {
  1109. hasMagic = pattern.toUpperCase() !== pattern.toLowerCase();
  1110. }
  1111. // skip the regexp for non-magical patterns
  1112. // unescape anything in it, though, so that it'll be
  1113. // an exact match against a file etc.
  1114. if (!hasMagic) {
  1115. return globUnescape(re);
  1116. }
  1117. const flags = (options.nocase ? 'i' : '') + (uflag ? 'u' : '');
  1118. try {
  1119. const ext = fastTest
  1120. ? {
  1121. _glob: pattern,
  1122. _src: re,
  1123. test: fastTest,
  1124. }
  1125. : {
  1126. _glob: pattern,
  1127. _src: re,
  1128. };
  1129. return Object.assign(new RegExp('^' + re + '$', flags), ext);
  1130. /* c8 ignore start */
  1131. }
  1132. catch (er) {
  1133. // should be impossible
  1134. // If it was an invalid regular expression, then it can't match
  1135. // anything. This trick looks for a character after the end of
  1136. // the string, which is of course impossible, except in multi-line
  1137. // mode, but it's not a /m regex.
  1138. this.debug('invalid regexp', er);
  1139. return new RegExp('$.');
  1140. }
  1141. /* c8 ignore stop */
  1142. }
  1143. makeRe() {
  1144. if (this.regexp || this.regexp === false)
  1145. return this.regexp;
  1146. // at this point, this.set is a 2d array of partial
  1147. // pattern strings, or "**".
  1148. //
  1149. // It's better to use .match(). This function shouldn't
  1150. // be used, really, but it's pretty convenient sometimes,
  1151. // when you just want to work with a regex.
  1152. const set = this.set;
  1153. if (!set.length) {
  1154. this.regexp = false;
  1155. return this.regexp;
  1156. }
  1157. const options = this.options;
  1158. const twoStar = options.noglobstar
  1159. ? star
  1160. : options.dot
  1161. ? twoStarDot
  1162. : twoStarNoDot;
  1163. const flags = options.nocase ? 'i' : '';
  1164. // regexpify non-globstar patterns
  1165. // if ** is only item, then we just do one twoStar
  1166. // if ** is first, and there are more, prepend (\/|twoStar\/)? to next
  1167. // if ** is last, append (\/twoStar|) to previous
  1168. // if ** is in the middle, append (\/|\/twoStar\/) to previous
  1169. // then filter out GLOBSTAR symbols
  1170. let re = set
  1171. .map(pattern => {
  1172. const pp = pattern.map(p => typeof p === 'string'
  1173. ? regExpEscape(p)
  1174. : p === exports.GLOBSTAR
  1175. ? exports.GLOBSTAR
  1176. : p._src);
  1177. pp.forEach((p, i) => {
  1178. const next = pp[i + 1];
  1179. const prev = pp[i - 1];
  1180. if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) {
  1181. return;
  1182. }
  1183. if (prev === undefined) {
  1184. if (next !== undefined && next !== exports.GLOBSTAR) {
  1185. pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
  1186. }
  1187. else {
  1188. pp[i] = twoStar;
  1189. }
  1190. }
  1191. else if (next === undefined) {
  1192. pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?';
  1193. }
  1194. else if (next !== exports.GLOBSTAR) {
  1195. pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
  1196. pp[i + 1] = exports.GLOBSTAR;
  1197. }
  1198. });
  1199. return pp.filter(p => p !== exports.GLOBSTAR).join('/');
  1200. })
  1201. .join('|');
  1202. // must match entire pattern
  1203. // ending in a * or ** will make it less strict.
  1204. re = '^(?:' + re + ')$';
  1205. // can match anything, as long as it's not this.
  1206. if (this.negate)
  1207. re = '^(?!' + re + ').*$';
  1208. try {
  1209. this.regexp = new RegExp(re, flags);
  1210. /* c8 ignore start */
  1211. }
  1212. catch (ex) {
  1213. // should be impossible
  1214. this.regexp = false;
  1215. }
  1216. /* c8 ignore stop */
  1217. return this.regexp;
  1218. }
  1219. slashSplit(p) {
  1220. // if p starts with // on windows, we preserve that
  1221. // so that UNC paths aren't broken. Otherwise, any number of
  1222. // / characters are coalesced into one, unless
  1223. // preserveMultipleSlashes is set to true.
  1224. if (this.preserveMultipleSlashes) {
  1225. return p.split('/');
  1226. }
  1227. else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
  1228. // add an extra '' for the one we lose
  1229. return ['', ...p.split(/\/+/)];
  1230. }
  1231. else {
  1232. return p.split(/\/+/);
  1233. }
  1234. }
  1235. match(f, partial = this.partial) {
  1236. this.debug('match', f, this.pattern);
  1237. // short-circuit in the case of busted things.
  1238. // comments, etc.
  1239. if (this.comment) {
  1240. return false;
  1241. }
  1242. if (this.empty) {
  1243. return f === '';
  1244. }
  1245. if (f === '/' && partial) {
  1246. return true;
  1247. }
  1248. const options = this.options;
  1249. // windows: need to use /, not \
  1250. if (this.isWindows) {
  1251. f = f.split('\\').join('/');
  1252. }
  1253. // treat the test path as a set of pathparts.
  1254. const ff = this.slashSplit(f);
  1255. this.debug(this.pattern, 'split', ff);
  1256. // just ONE of the pattern sets in this.set needs to match
  1257. // in order for it to be valid. If negating, then just one
  1258. // match means that we have failed.
  1259. // Either way, return on the first hit.
  1260. const set = this.set;
  1261. this.debug(this.pattern, 'set', set);
  1262. // Find the basename of the path by looking for the last non-empty segment
  1263. let filename = ff[ff.length - 1];
  1264. if (!filename) {
  1265. for (let i = ff.length - 2; !filename && i >= 0; i--) {
  1266. filename = ff[i];
  1267. }
  1268. }
  1269. for (let i = 0; i < set.length; i++) {
  1270. const pattern = set[i];
  1271. let file = ff;
  1272. if (options.matchBase && pattern.length === 1) {
  1273. file = [filename];
  1274. }
  1275. const hit = this.matchOne(file, pattern, partial);
  1276. if (hit) {
  1277. if (options.flipNegate) {
  1278. return true;
  1279. }
  1280. return !this.negate;
  1281. }
  1282. }
  1283. // didn't get any hits. this is success if it's a negative
  1284. // pattern, failure otherwise.
  1285. if (options.flipNegate) {
  1286. return false;
  1287. }
  1288. return this.negate;
  1289. }
  1290. static defaults(def) {
  1291. return exports.minimatch.defaults(def).Minimatch;
  1292. }
  1293. }
  1294. exports.Minimatch = Minimatch;
  1295. /* c8 ignore start */
  1296. var escape_js_2 = require("./escape.js");
  1297. Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } });
  1298. var unescape_js_2 = require("./unescape.js");
  1299. Object.defineProperty(exports, "unescape", { enumerable: true, get: function () { return unescape_js_2.unescape; } });
  1300. /* c8 ignore stop */
  1301. exports.minimatch.Minimatch = Minimatch;
  1302. exports.minimatch.escape = escape_js_1.escape;
  1303. exports.minimatch.unescape = unescape_js_1.unescape;
  1304. //# sourceMappingURL=index.js.map