@teammy/server 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +9835 -6799
- package/dist/native-pi-entry.js +14 -1
- package/dist/project-pi-entry.js +46 -8
- package/dist/runtime/workflows/task-bootstrap/prompt.md +2 -0
- package/dist/web/assets/{Assistant-B3h2yQF3.css → Assistant-4yZWjYm-.css} +1 -1
- package/dist/web/assets/Assistant-BNVXOHQZ.js +1 -0
- package/dist/web/assets/Dashboard-zKTK6EZD.js +1 -0
- package/dist/web/assets/Files-DI98WkdW.js +1 -0
- package/dist/web/assets/{Markdown-oZagG-wy.js → Markdown-D3cU0ani.js} +4 -4
- package/dist/web/assets/Materials-CK-mbNmo.css +1 -0
- package/dist/web/assets/Materials-CWptgAHz.js +6 -0
- package/dist/web/assets/Sessions-DiDwqXLI.js +1 -0
- package/dist/web/assets/WorkspaceTree-DeAA1QtV.js +1 -0
- package/dist/web/assets/{file-links-CD346_jf.js → file-links-GfCXWkEh.js} +1 -1
- package/dist/web/assets/index-BwEl1PIa.js +66 -0
- package/dist/web/assets/{index-Be5hGscJ.css → index-CTIAGUGG.css} +1 -1
- package/dist/web/downloads/teammy-skill.zip +0 -0
- package/dist/web/index.html +2 -2
- package/node_modules/@isaacs/nonrecursive-glob-match/LICENSE.md +55 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/README.md +333 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/index.d.ts +114 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/index.js +762 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/index.js.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/index.min.js +3 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/index.min.js.map +7 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/package.json +3 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/parse-class.d.ts +4 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/parse-class.d.ts.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/parse-class.js +142 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/commonjs/parse-class.js.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/index.d.ts +114 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/index.d.ts.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/index.js +758 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/index.js.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/index.min.js +3 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/index.min.js.map +7 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/package.json +3 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/parse-class.d.ts +4 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/parse-class.d.ts.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/parse-class.js +138 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/dist/esm/parse-class.js.map +1 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/package.json +56 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/src/index.ts +900 -0
- package/node_modules/@isaacs/nonrecursive-glob-match/src/parse-class.ts +158 -0
- package/node_modules/glob/README.md +388 -214
- package/node_modules/glob/dist/commonjs/glob.d.ts +20 -11
- package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/glob.js +22 -29
- package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
- package/node_modules/glob/dist/commonjs/has-magic.d.ts +1 -1
- package/node_modules/glob/dist/commonjs/has-magic.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/has-magic.js +1 -4
- package/node_modules/glob/dist/commonjs/has-magic.js.map +1 -1
- package/node_modules/glob/dist/commonjs/ignore.d.ts +16 -4
- package/node_modules/glob/dist/commonjs/ignore.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/ignore.js +24 -4
- package/node_modules/glob/dist/commonjs/ignore.js.map +1 -1
- package/node_modules/glob/dist/commonjs/index.d.ts +3 -2
- package/node_modules/glob/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/index.js.map +1 -1
- package/node_modules/glob/dist/commonjs/index.min.js +2 -3
- package/node_modules/glob/dist/commonjs/index.min.js.map +4 -4
- package/node_modules/glob/dist/commonjs/pattern.d.ts +10 -3
- package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/pattern.js +27 -15
- package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
- package/node_modules/glob/dist/commonjs/processor.d.ts +23 -10
- package/node_modules/glob/dist/commonjs/processor.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/processor.js +36 -23
- package/node_modules/glob/dist/commonjs/processor.js.map +1 -1
- package/node_modules/glob/dist/commonjs/walker.d.ts +19 -17
- package/node_modules/glob/dist/commonjs/walker.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/walker.js +50 -35
- package/node_modules/glob/dist/commonjs/walker.js.map +1 -1
- package/node_modules/glob/dist/esm/glob.d.ts +20 -11
- package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/glob.js +22 -29
- package/node_modules/glob/dist/esm/glob.js.map +1 -1
- package/node_modules/glob/dist/esm/has-magic.d.ts +1 -1
- package/node_modules/glob/dist/esm/has-magic.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/has-magic.js +1 -4
- package/node_modules/glob/dist/esm/has-magic.js.map +1 -1
- package/node_modules/glob/dist/esm/ignore.d.ts +16 -4
- package/node_modules/glob/dist/esm/ignore.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/ignore.js +25 -5
- package/node_modules/glob/dist/esm/ignore.js.map +1 -1
- package/node_modules/glob/dist/esm/index.d.ts +3 -2
- package/node_modules/glob/dist/esm/index.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/index.js.map +1 -1
- package/node_modules/glob/dist/esm/index.min.js +2 -3
- package/node_modules/glob/dist/esm/index.min.js.map +4 -4
- package/node_modules/glob/dist/esm/pattern.d.ts +10 -3
- package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/pattern.js +27 -15
- package/node_modules/glob/dist/esm/pattern.js.map +1 -1
- package/node_modules/glob/dist/esm/processor.d.ts +23 -10
- package/node_modules/glob/dist/esm/processor.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/processor.js +36 -23
- package/node_modules/glob/dist/esm/processor.js.map +1 -1
- package/node_modules/glob/dist/esm/walker.d.ts +19 -17
- package/node_modules/glob/dist/esm/walker.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/walker.js +51 -36
- package/node_modules/glob/dist/esm/walker.js.map +1 -1
- package/node_modules/glob/package.json +28 -12
- package/node_modules/glob/src/glob.ts +655 -0
- package/node_modules/glob/src/has-magic.ts +23 -0
- package/node_modules/glob/src/ignore.ts +162 -0
- package/node_modules/glob/src/index.ts +225 -0
- package/node_modules/glob/src/pattern.ts +286 -0
- package/node_modules/glob/src/processor.ts +333 -0
- package/node_modules/glob/src/walker.ts +523 -0
- package/node_modules/minimatch/README.md +125 -107
- package/node_modules/minimatch/dist/commonjs/index.d.ts +49 -38
- package/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/minimatch/dist/commonjs/index.js +782 -359
- package/node_modules/minimatch/dist/commonjs/index.js.map +1 -1
- package/node_modules/minimatch/dist/esm/index.d.ts +49 -38
- package/node_modules/minimatch/dist/esm/index.d.ts.map +1 -1
- package/node_modules/minimatch/dist/esm/index.js +781 -356
- package/node_modules/minimatch/dist/esm/index.js.map +1 -1
- package/node_modules/minimatch/package.json +5 -4
- package/node_modules/path-scurry/README.md +0 -1
- package/node_modules/path-scurry/dist/commonjs/index.d.ts +7 -0
- package/node_modules/path-scurry/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/path-scurry/dist/commonjs/index.js +59 -21
- package/node_modules/path-scurry/dist/commonjs/index.js.map +1 -1
- package/node_modules/path-scurry/dist/esm/index.d.ts +7 -0
- package/node_modules/path-scurry/dist/esm/index.d.ts.map +1 -1
- package/node_modules/path-scurry/dist/esm/index.js +42 -14
- package/node_modules/path-scurry/dist/esm/index.js.map +1 -1
- package/node_modules/path-scurry/package.json +4 -4
- package/package.json +2 -1
- package/dist/web/assets/Assistant-Dm_p8EZl.js +0 -1
- package/dist/web/assets/Dashboard-fwW9NxcC.js +0 -1
- package/dist/web/assets/Files-D-KCDWmO.js +0 -1
- package/dist/web/assets/Sessions-BQhGiLvz.js +0 -1
- package/dist/web/assets/WorkspaceTree-B9733pV3.js +0 -1
- package/dist/web/assets/index-BiiPuwDi.js +0 -66
- package/node_modules/minimatch/dist/commonjs/ast.d.ts +0 -22
- package/node_modules/minimatch/dist/commonjs/ast.d.ts.map +0 -1
- package/node_modules/minimatch/dist/commonjs/ast.js +0 -845
- package/node_modules/minimatch/dist/commonjs/ast.js.map +0 -1
- package/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts +0 -8
- package/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +0 -1
- package/node_modules/minimatch/dist/commonjs/brace-expressions.js +0 -150
- package/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +0 -1
- package/node_modules/minimatch/dist/esm/ast.d.ts +0 -22
- package/node_modules/minimatch/dist/esm/ast.d.ts.map +0 -1
- package/node_modules/minimatch/dist/esm/ast.js +0 -841
- package/node_modules/minimatch/dist/esm/ast.js.map +0 -1
- package/node_modules/minimatch/dist/esm/brace-expressions.d.ts +0 -8
- package/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +0 -1
- package/node_modules/minimatch/dist/esm/brace-expressions.js +0 -146
- package/node_modules/minimatch/dist/esm/brace-expressions.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.unescape = exports.escape = exports.
|
|
3
|
+
exports.unescape = exports.escape = exports.Minimatch = exports.match = exports.braceExpand = exports.defaults = exports.filter = exports.GLOBSTAR = exports.sep = exports.minimatch = void 0;
|
|
4
4
|
const brace_expansion_1 = require("brace-expansion");
|
|
5
|
+
const nonrecursive_glob_match_1 = require("@isaacs/nonrecursive-glob-match");
|
|
5
6
|
const assert_valid_pattern_js_1 = require("./assert-valid-pattern.js");
|
|
6
|
-
const ast_js_1 = require("./ast.js");
|
|
7
7
|
const escape_js_1 = require("./escape.js");
|
|
8
8
|
const unescape_js_1 = require("./unescape.js");
|
|
9
9
|
const minimatch = (p, pattern, options = {}) => {
|
|
@@ -12,66 +12,33 @@ const minimatch = (p, pattern, options = {}) => {
|
|
|
12
12
|
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
|
-
return
|
|
15
|
+
return cachedMinimatch(pattern, options).match(p);
|
|
16
16
|
};
|
|
17
17
|
exports.minimatch = minimatch;
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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 !== '..';
|
|
18
|
+
// The Minimatch objects that minimatch() used most recently. A Map
|
|
19
|
+
// keeps its keys in the order they were set, so the first key is the
|
|
20
|
+
// one used least recently.
|
|
21
|
+
const cache = new Map();
|
|
22
|
+
const cacheMax = 256;
|
|
23
|
+
const cachedMinimatch = (pattern, options) => {
|
|
24
|
+
const key = pattern + '\0' + JSON.stringify(options);
|
|
25
|
+
let mm = cache.get(key);
|
|
26
|
+
if (mm) {
|
|
27
|
+
cache.delete(key);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// a copy, so a later change to the options can not change it
|
|
31
|
+
mm = new Minimatch(pattern, { ...options });
|
|
32
|
+
if (cache.size >= cacheMax) {
|
|
33
|
+
cache.delete(cache.keys().next().value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
cache.set(key, mm);
|
|
37
|
+
return mm;
|
|
68
38
|
};
|
|
69
39
|
/* c8 ignore start */
|
|
70
40
|
const defaultPlatform = (typeof process === 'object' && process ?
|
|
71
|
-
|
|
72
|
-
process.env &&
|
|
73
|
-
process.env.__MINIMATCH_TESTING_PLATFORM__) ||
|
|
74
|
-
process.platform
|
|
41
|
+
process.env?.__MINIMATCH_TESTING_PLATFORM__ || process.platform
|
|
75
42
|
: 'posix');
|
|
76
43
|
const path = {
|
|
77
44
|
win32: { sep: '\\' },
|
|
@@ -82,18 +49,6 @@ exports.sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep;
|
|
|
82
49
|
exports.minimatch.sep = exports.sep;
|
|
83
50
|
exports.GLOBSTAR = Symbol('globstar **');
|
|
84
51
|
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
52
|
const filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options);
|
|
98
53
|
exports.filter = filter;
|
|
99
54
|
exports.minimatch.filter = exports.filter;
|
|
@@ -113,21 +68,10 @@ const defaults = (def) => {
|
|
|
113
68
|
return orig.defaults(ext(def, options)).Minimatch;
|
|
114
69
|
}
|
|
115
70
|
},
|
|
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
71
|
unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
|
|
127
72
|
escape: (s, options = {}) => orig.escape(s, ext(def, options)),
|
|
128
73
|
filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
|
|
129
74
|
defaults: (options) => orig.defaults(ext(def, options)),
|
|
130
|
-
makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
|
|
131
75
|
braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
|
|
132
76
|
match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
|
|
133
77
|
sep: orig.sep,
|
|
@@ -158,20 +102,6 @@ const braceExpand = (pattern, options = {}) => {
|
|
|
158
102
|
};
|
|
159
103
|
exports.braceExpand = braceExpand;
|
|
160
104
|
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
105
|
const match = (list, pattern, options = {}) => {
|
|
176
106
|
const mm = new Minimatch(pattern, options);
|
|
177
107
|
list = list.filter(f => mm.match(f));
|
|
@@ -182,9 +112,201 @@ const match = (list, pattern, options = {}) => {
|
|
|
182
112
|
};
|
|
183
113
|
exports.match = match;
|
|
184
114
|
exports.minimatch.match = exports.match;
|
|
185
|
-
// replace stuff like \* with *
|
|
186
115
|
const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
|
|
187
|
-
|
|
116
|
+
// Index of the `]` that closes the class that starts at `start`,
|
|
117
|
+
// or -1 if it is not closed. Posix classes such as `[:alpha:]` are
|
|
118
|
+
// not skipped, so this can find a `]` before the real end. That
|
|
119
|
+
// only makes a class look less like a literal.
|
|
120
|
+
const classEnd = (pattern, start) => {
|
|
121
|
+
let i = start + 1;
|
|
122
|
+
if (pattern.charAt(i) === '!' || pattern.charAt(i) === '^')
|
|
123
|
+
i++;
|
|
124
|
+
let sawStart = false;
|
|
125
|
+
for (; i < pattern.length; i++) {
|
|
126
|
+
const c = pattern.charAt(i);
|
|
127
|
+
if (c === ']' && sawStart)
|
|
128
|
+
return i;
|
|
129
|
+
sawStart = true;
|
|
130
|
+
if (c === '\\')
|
|
131
|
+
i++;
|
|
132
|
+
}
|
|
133
|
+
return -1;
|
|
134
|
+
};
|
|
135
|
+
// If a path portion pattern has no magic, return the string it
|
|
136
|
+
// matches. Otherwise, return undefined. This can report magic for
|
|
137
|
+
// a pattern that is in fact literal (eg, `[]`), but never the
|
|
138
|
+
// reverse, so a string result is always safe to compare directly.
|
|
139
|
+
const literal = (pattern, noext) => {
|
|
140
|
+
if (!noext && (pattern === '+()' || pattern === '@()'))
|
|
141
|
+
return pattern;
|
|
142
|
+
let lit = '';
|
|
143
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
144
|
+
const c = pattern.charAt(i);
|
|
145
|
+
if (c === '\\') {
|
|
146
|
+
// a trailing \ is a literal \
|
|
147
|
+
lit += pattern.charAt(++i) || c;
|
|
148
|
+
}
|
|
149
|
+
else if (c === '*' || c === '?') {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
else if (c === '[') {
|
|
153
|
+
const close = classEnd(pattern, i);
|
|
154
|
+
if (close === -1) {
|
|
155
|
+
// not closed, so the [ is a literal
|
|
156
|
+
lit += c;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
// a class of one char, such as `[*]` or `[\b]`, is a literal
|
|
160
|
+
let body = pattern.slice(i + 1, close);
|
|
161
|
+
if (body.startsWith('\\'))
|
|
162
|
+
body = body.slice(1);
|
|
163
|
+
if ([...body].length !== 1 || '!^'.includes(pattern.charAt(i + 1))) {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
lit += body;
|
|
167
|
+
i = close;
|
|
168
|
+
}
|
|
169
|
+
else if (!noext &&
|
|
170
|
+
'+@!'.includes(c) &&
|
|
171
|
+
pattern.charAt(i + 1) === '(' &&
|
|
172
|
+
pattern.includes(')', i + 2)) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
lit += c;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return lit;
|
|
180
|
+
};
|
|
181
|
+
// True if the portion pattern has the same meaning as an alternative
|
|
182
|
+
// inside `@(...)`. It must not have a `|` or `)` that is not in a
|
|
183
|
+
// closed extglob (those are literal at the top level), an extglob
|
|
184
|
+
// that is not closed (the `)` of the `@(...)` would close it), or a
|
|
185
|
+
// trailing `\` (it would escape the next `|`). A pattern that is
|
|
186
|
+
// only an empty extglob, such as `?()`, is literal on its own, but
|
|
187
|
+
// not in `@(...)`. Posix classes such as `[:alpha:]` can hide a `]`
|
|
188
|
+
// from classEnd, so patterns with them are not merged.
|
|
189
|
+
const extSafe = (pattern) => {
|
|
190
|
+
if (/^[?*+@]\(\)$/.test(pattern) || pattern.includes('[:'))
|
|
191
|
+
return false;
|
|
192
|
+
let depth = 0;
|
|
193
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
194
|
+
const c = pattern.charAt(i);
|
|
195
|
+
if (c === '\\') {
|
|
196
|
+
if (++i === pattern.length)
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
else if (c === '[') {
|
|
200
|
+
const close = classEnd(pattern, i);
|
|
201
|
+
if (close !== -1)
|
|
202
|
+
i = close;
|
|
203
|
+
}
|
|
204
|
+
else if ('+@!?*'.includes(c) && pattern.charAt(i + 1) === '(') {
|
|
205
|
+
depth++;
|
|
206
|
+
i++;
|
|
207
|
+
}
|
|
208
|
+
else if (c === ')') {
|
|
209
|
+
if (!depth--)
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
else if (c === '|' && !depth) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return !depth;
|
|
217
|
+
};
|
|
218
|
+
// The last path that Minimatch#match split, and its parts. A path is
|
|
219
|
+
// often tested against many patterns in a row (such as a list of
|
|
220
|
+
// ignore patterns), so this saves splitting it again. The parts are
|
|
221
|
+
// never changed, so they can be shared.
|
|
222
|
+
let lastSplit;
|
|
223
|
+
// The last path that Minimatch#match checked before splitting it. If
|
|
224
|
+
// the same path is checked again, it is being tested against many
|
|
225
|
+
// patterns, so it is split and the parts are kept for the others.
|
|
226
|
+
let lastChecked;
|
|
227
|
+
// true if a pattern portion that is not ** matches a path portion.
|
|
228
|
+
// An empty path portion only matches an empty pattern portion. A path
|
|
229
|
+
// portion never has a `/`, so the Matcher does not need to check it.
|
|
230
|
+
const portionMatch = (p, f) => typeof p === 'string' ? f === p : f !== '' && p.testUnchecked(f);
|
|
231
|
+
// Where the last portion of a row matches in a path: the start of the
|
|
232
|
+
// last portion of the path, or of the one before a trailing `/`. -1 if
|
|
233
|
+
// it matches neither.
|
|
234
|
+
const endIndex = (p, last, lastStart, prev, prevStart) => portionMatch(p, last) ? lastStart
|
|
235
|
+
: prev !== undefined && portionMatch(p, prev) ? prevStart
|
|
236
|
+
: -1;
|
|
237
|
+
const isDots = (p) => p === '.' || p === '..';
|
|
238
|
+
// a Windows drive letter portion, like `c:`
|
|
239
|
+
const isDrive = (p) => typeof p === 'string' && /^[a-z]:$/i.test(p);
|
|
240
|
+
// true for the `UNC` portion of a long UNC root, //?/UNC/host/share
|
|
241
|
+
const isLongUNC = (p) => typeof p === 'string' && /^unc$/i.test(p);
|
|
242
|
+
// The index of the host in a row or split path that starts with a
|
|
243
|
+
// Windows UNC root: 2 for `//host/share`, and 4 for
|
|
244
|
+
// `//?/UNC/host/share`. Otherwise -1. `//?/c:` is not one.
|
|
245
|
+
const uncHost = (p) => {
|
|
246
|
+
if (p[0] !== '' || p[1] !== '')
|
|
247
|
+
return -1;
|
|
248
|
+
const h = p[2] !== '?' ? 2
|
|
249
|
+
: isLongUNC(p[3]) ? 4
|
|
250
|
+
: -1;
|
|
251
|
+
const host = p[h];
|
|
252
|
+
const share = p[h + 1];
|
|
253
|
+
return (h !== -1 &&
|
|
254
|
+
host !== undefined &&
|
|
255
|
+
host !== '' &&
|
|
256
|
+
host !== exports.GLOBSTAR &&
|
|
257
|
+
share !== undefined &&
|
|
258
|
+
share !== '' &&
|
|
259
|
+
share !== exports.GLOBSTAR) ?
|
|
260
|
+
h
|
|
261
|
+
: -1;
|
|
262
|
+
};
|
|
263
|
+
// true if ** can walk the path portion: not `.` or `..`, and not a
|
|
264
|
+
// dotfile unless `dot` is set
|
|
265
|
+
const walkable = (p, dot) => !isDots(p) && (dot || !p.startsWith('.'));
|
|
266
|
+
// True if a portion of the path from `start` to `end` can not be
|
|
267
|
+
// walked by **: one that starts with `.`, or with `dot`, one that is
|
|
268
|
+
// `.` or `..`. `start` is the start of a portion, and `end` is the end
|
|
269
|
+
// of the path, or just after a separator.
|
|
270
|
+
const dotPortion = (f, start, end, dot, sep) => {
|
|
271
|
+
for (let k = start; k < end;) {
|
|
272
|
+
if (f.charCodeAt(k) === 46) {
|
|
273
|
+
if (!dot)
|
|
274
|
+
return true;
|
|
275
|
+
const n = f.charCodeAt(k + 1) === 46 ? k + 2 : k + 1;
|
|
276
|
+
if (n >= end || isSep(f.charCodeAt(n), sep))
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
// the start of the next portion, after any run of separators
|
|
280
|
+
const s = nextSep(f, k, sep);
|
|
281
|
+
if (s === -1)
|
|
282
|
+
return false;
|
|
283
|
+
k = s + 1;
|
|
284
|
+
while (k < end && isSep(f.charCodeAt(k), sep))
|
|
285
|
+
k++;
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
};
|
|
289
|
+
const isSep = (c, sep) => sep === '/' ? c === 47
|
|
290
|
+
: sep === '\\' ? c === 92
|
|
291
|
+
: c === 47 || c === 92;
|
|
292
|
+
// the index of the first separator at or after `from`, or -1
|
|
293
|
+
const nextSep = (f, from, sep) => {
|
|
294
|
+
if (sep !== 'both')
|
|
295
|
+
return f.indexOf(sep, from);
|
|
296
|
+
const s = f.indexOf('/', from);
|
|
297
|
+
const b = f.indexOf('\\', from);
|
|
298
|
+
return (s === -1 ? b
|
|
299
|
+
: b === -1 ? s
|
|
300
|
+
: Math.min(s, b));
|
|
301
|
+
};
|
|
302
|
+
// the index of the last separator at or before `from`, or -1
|
|
303
|
+
const lastSep = (f, from, sep) => sep !== 'both' ?
|
|
304
|
+
f.lastIndexOf(sep, from)
|
|
305
|
+
: Math.max(f.lastIndexOf('/', from), f.lastIndexOf('\\', from));
|
|
306
|
+
// What parse() returns in place of a Matcher while make() builds and
|
|
307
|
+
// merges the rows. Most of the Matchers in rows that are merged would
|
|
308
|
+
// never be used, so they are only made for the rows that are left.
|
|
309
|
+
const PENDING = {};
|
|
188
310
|
class Minimatch {
|
|
189
311
|
options;
|
|
190
312
|
set;
|
|
@@ -203,7 +325,27 @@ class Minimatch {
|
|
|
203
325
|
platform;
|
|
204
326
|
windowsNoMagicRoot;
|
|
205
327
|
maxGlobstarRecursion;
|
|
206
|
-
|
|
328
|
+
// the path can be checked against the last portion, and the string
|
|
329
|
+
// portions, of each row before it is split. See #canMatch.
|
|
330
|
+
#endCheck;
|
|
331
|
+
#literalCheck;
|
|
332
|
+
// level 2 resolves `.` and `..` portions in the path
|
|
333
|
+
#level2;
|
|
334
|
+
// the unicode normalization form, if any
|
|
335
|
+
#form;
|
|
336
|
+
// the string portions of each row in the set
|
|
337
|
+
#literals = [];
|
|
338
|
+
// the rows that #canMatch can match without splitting the path
|
|
339
|
+
#shapes = [];
|
|
340
|
+
// the rows whose last portion can be checked against the path's
|
|
341
|
+
#endRows = [];
|
|
342
|
+
// brace expansion can make the same portion in many rows, so they
|
|
343
|
+
// share one Matcher, and the states that it caches
|
|
344
|
+
#matchers = new Map();
|
|
345
|
+
// parse() returns PENDING in place of a Matcher
|
|
346
|
+
#pending = false;
|
|
347
|
+
// the GlobstarParts of each pattern row, by start index and partial
|
|
348
|
+
#globstarParts = new WeakMap();
|
|
207
349
|
constructor(pattern, options = {}) {
|
|
208
350
|
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
209
351
|
options = options || {};
|
|
@@ -220,7 +362,6 @@ class Minimatch {
|
|
|
220
362
|
this.pattern = this.pattern.replace(/\\/g, '/');
|
|
221
363
|
}
|
|
222
364
|
this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
|
|
223
|
-
this.regexp = null;
|
|
224
365
|
this.negate = false;
|
|
225
366
|
this.nonegate = !!options.nonegate;
|
|
226
367
|
this.comment = false;
|
|
@@ -234,8 +375,81 @@ class Minimatch {
|
|
|
234
375
|
this.globSet = [];
|
|
235
376
|
this.globParts = [];
|
|
236
377
|
this.set = [];
|
|
237
|
-
|
|
378
|
+
this.#endCheck = !this.preserveMultipleSlashes;
|
|
379
|
+
this.#level2 = (options.optimizationLevel ?? 1) >= 2;
|
|
380
|
+
const n = options.normalize;
|
|
381
|
+
this.#form = n === true ? 'NFC' : n || undefined;
|
|
382
|
+
// make the set of Matchers etc.
|
|
238
383
|
this.make();
|
|
384
|
+
// On Windows, the portions of a row up to its drive letter or UNC
|
|
385
|
+
// share are skipped or compared without case, if the path has one
|
|
386
|
+
// too. So the checks only use the portions after it.
|
|
387
|
+
const drives = this.set.map(row => this.#rootIndex(row));
|
|
388
|
+
this.#endRows = this.set.map((row, r) => this.#endCheck && row.length - 1 > drives[r]);
|
|
389
|
+
// with the end check, the last portion is already checked
|
|
390
|
+
this.#literals = this.set.map((row, r) => {
|
|
391
|
+
const end = this.#endRows[r] ? row.length - 1 : row.length;
|
|
392
|
+
const lits = row
|
|
393
|
+
.slice(drives[r] + 1, end)
|
|
394
|
+
.filter((p) => typeof p === 'string' && !!p);
|
|
395
|
+
return [...new Set(lits)];
|
|
396
|
+
});
|
|
397
|
+
this.#literalCheck = this.#literals.some(l => l.length);
|
|
398
|
+
this.#shapes = this.set.map((row, r) => {
|
|
399
|
+
const [p0, p1, p2] = row;
|
|
400
|
+
if (this.#endRows[r] && row.length === 2) {
|
|
401
|
+
if (p0 === exports.GLOBSTAR && p1 !== exports.GLOBSTAR)
|
|
402
|
+
return 'tail';
|
|
403
|
+
}
|
|
404
|
+
// the basename of a path that is split on / is its last portion,
|
|
405
|
+
// or the one before a trailing /, the same as the end check
|
|
406
|
+
if (this.#endRows[r] &&
|
|
407
|
+
options.matchBase &&
|
|
408
|
+
row.length === 1 &&
|
|
409
|
+
p0 !== exports.GLOBSTAR &&
|
|
410
|
+
p0 !== '') {
|
|
411
|
+
return 'base';
|
|
412
|
+
}
|
|
413
|
+
// the portion must not be a root, or '', which can be a
|
|
414
|
+
// different portion on Windows (where //x paths get an extra '')
|
|
415
|
+
if (!this.#endCheck || drives[r] !== -1)
|
|
416
|
+
return undefined;
|
|
417
|
+
if (row.length === 3 &&
|
|
418
|
+
p0 === exports.GLOBSTAR &&
|
|
419
|
+
p2 === exports.GLOBSTAR &&
|
|
420
|
+
p1 !== exports.GLOBSTAR &&
|
|
421
|
+
p1 !== '' &&
|
|
422
|
+
// the portion between is only matched below this limit
|
|
423
|
+
this.maxGlobstarRecursion > 0) {
|
|
424
|
+
return 'mid';
|
|
425
|
+
}
|
|
426
|
+
if (row.length === 2 &&
|
|
427
|
+
p1 === exports.GLOBSTAR &&
|
|
428
|
+
p0 !== exports.GLOBSTAR &&
|
|
429
|
+
p0 !== '') {
|
|
430
|
+
return 'head';
|
|
431
|
+
}
|
|
432
|
+
return undefined;
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
// a string portion of a pattern, normalized if the option is set
|
|
436
|
+
#norm(p) {
|
|
437
|
+
return this.#form ? p.normalize(this.#form) : p;
|
|
438
|
+
}
|
|
439
|
+
// On Windows, the index of the last root portion of a row, as
|
|
440
|
+
// #matchRow finds it: 0 for `c:/...`, 3 for `//?/c:/...` and
|
|
441
|
+
// `//host/share/...`, and 5 for `//?/UNC/host/share/...`. Otherwise
|
|
442
|
+
// -1.
|
|
443
|
+
#rootIndex(row) {
|
|
444
|
+
if (!this.isWindows)
|
|
445
|
+
return -1;
|
|
446
|
+
if (isDrive(row[0]))
|
|
447
|
+
return 0;
|
|
448
|
+
const uncDrive = row[0] === '' && row[1] === '' && row[2] === '?' && isDrive(row[3]);
|
|
449
|
+
if (uncDrive)
|
|
450
|
+
return 3;
|
|
451
|
+
const h = uncHost(row);
|
|
452
|
+
return h === -1 ? -1 : h + 1;
|
|
239
453
|
}
|
|
240
454
|
hasMagic() {
|
|
241
455
|
if (this.options.magicalBraces && this.set.length > 1) {
|
|
@@ -249,7 +463,6 @@ class Minimatch {
|
|
|
249
463
|
}
|
|
250
464
|
return false;
|
|
251
465
|
}
|
|
252
|
-
debug(..._) { }
|
|
253
466
|
make() {
|
|
254
467
|
const pattern = this.pattern;
|
|
255
468
|
const options = this.options;
|
|
@@ -266,45 +479,44 @@ class Minimatch {
|
|
|
266
479
|
this.parseNegate();
|
|
267
480
|
// step 2: expand braces
|
|
268
481
|
this.globSet = [...new Set(this.braceExpand())];
|
|
269
|
-
if (options.debug) {
|
|
270
|
-
//oxlint-disable-next-line no-console
|
|
271
|
-
this.debug = (...args) => console.error(...args);
|
|
272
|
-
}
|
|
273
|
-
this.debug(this.pattern, this.globSet);
|
|
274
482
|
// step 3: now we have a set, so turn each one into a series of
|
|
275
483
|
// path-portion matching patterns.
|
|
276
|
-
// These will be
|
|
484
|
+
// These will be Matchers, except in the case of "**", which is
|
|
277
485
|
// set to the GLOBSTAR object for globstar behavior,
|
|
278
486
|
// and will not contain any / characters
|
|
279
487
|
//
|
|
280
488
|
// First, we preprocess to make the glob pattern sets a bit simpler
|
|
281
489
|
// and deduped. There are some perf-killing patterns that can cause
|
|
282
490
|
// problems with a glob walk, but we can simplify them down a bit.
|
|
283
|
-
const rawGlobParts = this.globSet.map(s => this
|
|
491
|
+
const rawGlobParts = this.globSet.map(s => this.#slashSplit(s));
|
|
284
492
|
this.globParts = this.preprocess(rawGlobParts);
|
|
285
|
-
|
|
286
|
-
|
|
493
|
+
// glob --> Matchers
|
|
494
|
+
this.#pending = true;
|
|
287
495
|
let set = this.globParts.map((s, _, __) => {
|
|
288
496
|
if (this.isWindows && this.windowsNoMagicRoot) {
|
|
289
|
-
// check if it's a drive or unc path.
|
|
497
|
+
// check if it's a drive or unc path. The root of a long UNC
|
|
498
|
+
// path, //?/UNC/host/share, is 6 portions.
|
|
499
|
+
const n = s[2] === '?' && isLongUNC(s[3]) ? 6 : 4;
|
|
290
500
|
const isUNC = s[0] === '' &&
|
|
291
501
|
s[1] === '' &&
|
|
292
502
|
(s[2] === '?' || !globMagic.test(s[2])) &&
|
|
293
|
-
!globMagic.test(
|
|
503
|
+
s.slice(3, n).every(p => !globMagic.test(p));
|
|
294
504
|
const isDrive = /^[a-z]:/i.test(s[0]);
|
|
295
505
|
if (isUNC) {
|
|
296
506
|
return [
|
|
297
|
-
...s.slice(0,
|
|
298
|
-
...s.slice(
|
|
507
|
+
...s.slice(0, n).map(p => this.#norm(p)),
|
|
508
|
+
...s.slice(n).map(ss => this.parse(ss)),
|
|
299
509
|
];
|
|
300
510
|
}
|
|
301
511
|
else if (isDrive) {
|
|
302
|
-
return [
|
|
512
|
+
return [
|
|
513
|
+
this.#norm(s[0]),
|
|
514
|
+
...s.slice(1).map(ss => this.parse(ss)),
|
|
515
|
+
];
|
|
303
516
|
}
|
|
304
517
|
}
|
|
305
518
|
return s.map(ss => this.parse(ss));
|
|
306
519
|
});
|
|
307
|
-
this.debug(this.pattern, set);
|
|
308
520
|
// filter out everything that didn't compile properly.
|
|
309
521
|
this.set = set.filter(s => s.indexOf(false) === -1);
|
|
310
522
|
// do not treat the ? in UNC paths as magic
|
|
@@ -314,13 +526,70 @@ class Minimatch {
|
|
|
314
526
|
if (p[0] === '' &&
|
|
315
527
|
p[1] === '' &&
|
|
316
528
|
this.globParts[i][2] === '?' &&
|
|
317
|
-
|
|
318
|
-
|
|
529
|
+
(isDrive(p[3]) || isLongUNC(this.globParts[i][3]))) {
|
|
530
|
+
if (isLongUNC(this.globParts[i][3]))
|
|
531
|
+
p[3] = 'UNC';
|
|
319
532
|
p[2] = '?';
|
|
320
533
|
}
|
|
321
534
|
}
|
|
322
535
|
}
|
|
323
|
-
|
|
536
|
+
// with noext, `@(...)` would be literal
|
|
537
|
+
if (!options.noext)
|
|
538
|
+
this.mergeRows();
|
|
539
|
+
this.#pending = false;
|
|
540
|
+
this.set.forEach((row, i) => {
|
|
541
|
+
for (let k = 0; k < row.length; k++) {
|
|
542
|
+
if (row[k] === PENDING) {
|
|
543
|
+
row[k] = this.parse(this.globParts[i][k]);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
// Merge rows that only differ in one portion, where each of them
|
|
549
|
+
// is a Matcher, into one row that matches any of them with
|
|
550
|
+
// `@(a|b|...)`. Then a path is only walked once for all of them,
|
|
551
|
+
// for example with `**/*.{js,ts}`.
|
|
552
|
+
mergeRows() {
|
|
553
|
+
let merged = true;
|
|
554
|
+
while (merged) {
|
|
555
|
+
merged = false;
|
|
556
|
+
const len = Math.max(0, ...this.set.map(r => r.length));
|
|
557
|
+
for (let k = 0; k < len; k++) {
|
|
558
|
+
// the rows that are the same other than at portion k
|
|
559
|
+
const groups = new Map();
|
|
560
|
+
this.set.forEach((row, i) => {
|
|
561
|
+
if (!(row[k] instanceof nonrecursive_glob_match_1.Matcher || row[k] === PENDING) ||
|
|
562
|
+
!extSafe(this.globParts[i][k])) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const parts = [...this.globParts[i]];
|
|
566
|
+
parts[k] = '';
|
|
567
|
+
const key = `${row.length}/${parts.join('/')}`;
|
|
568
|
+
const g = groups.get(key);
|
|
569
|
+
if (g)
|
|
570
|
+
g.push(i);
|
|
571
|
+
else
|
|
572
|
+
groups.set(key, [i]);
|
|
573
|
+
});
|
|
574
|
+
const drop = new Set();
|
|
575
|
+
for (const g of groups.values()) {
|
|
576
|
+
if (g.length < 2)
|
|
577
|
+
continue;
|
|
578
|
+
const [first, ...rest] = g;
|
|
579
|
+
const alts = g.map(i => this.globParts[i][k]);
|
|
580
|
+
const glob = `@(${alts.join('|')})`;
|
|
581
|
+
this.globParts[first][k] = glob;
|
|
582
|
+
this.set[first][k] = this.parse(glob);
|
|
583
|
+
for (const i of rest)
|
|
584
|
+
drop.add(i);
|
|
585
|
+
}
|
|
586
|
+
if (drop.size) {
|
|
587
|
+
merged = true;
|
|
588
|
+
this.set = this.set.filter((_, i) => !drop.has(i));
|
|
589
|
+
this.globParts = this.globParts.filter((_, i) => !drop.has(i));
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
324
593
|
}
|
|
325
594
|
// various transforms to equivalent pattern sets that are
|
|
326
595
|
// faster to process in a filesystem walk. The goal is to
|
|
@@ -373,13 +642,19 @@ class Minimatch {
|
|
|
373
642
|
// get rid of adjascent ** and resolve .. portions
|
|
374
643
|
levelOneOptimize(globParts) {
|
|
375
644
|
return globParts.map(parts => {
|
|
645
|
+
// .. can not remove the root of a Windows path
|
|
646
|
+
const root = this.#rootIndex(parts) + 1;
|
|
376
647
|
parts = parts.reduce((set, part) => {
|
|
377
648
|
const prev = set[set.length - 1];
|
|
378
649
|
if (part === '**' && prev === '**') {
|
|
379
650
|
return set;
|
|
380
651
|
}
|
|
381
652
|
if (part === '..') {
|
|
382
|
-
if (
|
|
653
|
+
if (set.length > root &&
|
|
654
|
+
prev &&
|
|
655
|
+
prev !== '..' &&
|
|
656
|
+
prev !== '.' &&
|
|
657
|
+
prev !== '**') {
|
|
383
658
|
set.pop();
|
|
384
659
|
return set;
|
|
385
660
|
}
|
|
@@ -390,10 +665,214 @@ class Minimatch {
|
|
|
390
665
|
return parts.length === 0 ? [''] : parts;
|
|
391
666
|
});
|
|
392
667
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
668
|
+
// Check the path against each row before it is split. 'no' if no
|
|
669
|
+
// row can match, so it does not need to be split. 'yes' if a row of
|
|
670
|
+
// `**` and one more portion matches. 'maybe' if it must be split to
|
|
671
|
+
// know. None of this applies with partial, where the path can end
|
|
672
|
+
// before the row does.
|
|
673
|
+
//
|
|
674
|
+
// On Windows, `\` is a separator in the path too, and the portions of
|
|
675
|
+
// a row up to its drive letter or UNC share are not checked (see
|
|
676
|
+
// #rootIndex).
|
|
677
|
+
//
|
|
678
|
+
// Each string portion of a row must be a portion of the path, so the
|
|
679
|
+
// path must contain it. Level 2 can only take portions out of the
|
|
680
|
+
// path, so this is still true then.
|
|
681
|
+
//
|
|
682
|
+
// The last portion of a row must match the last portion of the path,
|
|
683
|
+
// or the one before a trailing `/` (as a/* and a/**/* match a/b/).
|
|
684
|
+
// This does not apply to rows that end in **, rows that end in a
|
|
685
|
+
// root, or preserveMultipleSlashes (which can leave more
|
|
686
|
+
// than one '' at the end). At level 2, it does not apply if that
|
|
687
|
+
// portion is `.` or `..`, which can be
|
|
688
|
+
// resolved away. Level 2 only takes other portions out of the
|
|
689
|
+
// middle of the path.
|
|
690
|
+
//
|
|
691
|
+
// A row of `**/x` then matches if the ** can walk the portions
|
|
692
|
+
// before the one that x matches, the same as #matchGlobstar. At
|
|
693
|
+
// level 2, this is only known if none of them are `.` or `..`, so
|
|
694
|
+
// that the path does not change when it is resolved.
|
|
695
|
+
#canMatch(f) {
|
|
696
|
+
const sep = !this.isWindows || !f.includes('\\') ? '/'
|
|
697
|
+
: f.includes('/') ? 'both'
|
|
698
|
+
: '\\';
|
|
699
|
+
// the portions that f.split(/\/+/) would end with, and where they
|
|
700
|
+
// start in f, found when a row needs them. `ends` is 0 until they
|
|
701
|
+
// are found, then 1, or -1 if they can not be used.
|
|
702
|
+
let ends = this.#endCheck ? 0 : -1;
|
|
703
|
+
let last = '';
|
|
704
|
+
let lastStart = 0;
|
|
705
|
+
let prev;
|
|
706
|
+
let prevStart = 0;
|
|
707
|
+
const dot = !!this.options.dot;
|
|
708
|
+
// A string compare is cheaper than includes(), and a Matcher test
|
|
709
|
+
// costs more, so the cheaper check goes first.
|
|
710
|
+
ROWS: for (let r = 0; r < this.set.length; r++) {
|
|
711
|
+
const row = this.set[r];
|
|
712
|
+
const p = row[row.length - 1];
|
|
713
|
+
let end = ends !== -1 && this.#endRows[r] && p !== exports.GLOBSTAR;
|
|
714
|
+
if (end && ends === 0) {
|
|
715
|
+
const i = lastSep(f, f.length, sep);
|
|
716
|
+
lastStart = i + 1;
|
|
717
|
+
last = f.slice(lastStart);
|
|
718
|
+
if (last === '' && i >= 0) {
|
|
719
|
+
let j = i;
|
|
720
|
+
while (j > 0 && isSep(f.charCodeAt(j - 1), sep))
|
|
721
|
+
j--;
|
|
722
|
+
prevStart = j === 0 ? 0 : lastSep(f, j - 1, sep) + 1;
|
|
723
|
+
prev = f.slice(prevStart, j);
|
|
724
|
+
}
|
|
725
|
+
const resolves = this.#level2 &&
|
|
726
|
+
(isDots(last) ||
|
|
727
|
+
(last === '' && prev !== undefined && isDots(prev)));
|
|
728
|
+
ends = resolves ? -1 : 1;
|
|
729
|
+
end = !resolves;
|
|
730
|
+
}
|
|
731
|
+
let tailStart = -1;
|
|
732
|
+
if (end && typeof p === 'string') {
|
|
733
|
+
tailStart = endIndex(p, last, lastStart, prev, prevStart);
|
|
734
|
+
if (tailStart === -1)
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
if (this.#literalCheck) {
|
|
738
|
+
for (const l of this.#literals[r]) {
|
|
739
|
+
if (!f.includes(l))
|
|
740
|
+
continue ROWS;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
if (end && typeof p === 'object') {
|
|
744
|
+
tailStart = endIndex(p, last, lastStart, prev, prevStart);
|
|
745
|
+
if (tailStart === -1)
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
const shape = this.#shapes[r];
|
|
749
|
+
if (shape === 'base' && end)
|
|
750
|
+
return 'yes';
|
|
751
|
+
if (shape === 'tail' && end) {
|
|
752
|
+
if (this.#level2 && dotPortion(f, 0, tailStart, true, sep)) {
|
|
753
|
+
return 'maybe';
|
|
754
|
+
}
|
|
755
|
+
if (!dotPortion(f, 0, tailStart, dot, sep))
|
|
756
|
+
return 'yes';
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
if (shape === 'mid' || shape === 'head') {
|
|
760
|
+
const m = this.#walk(f, row, shape === 'head', dot, sep);
|
|
761
|
+
if (m !== 'no')
|
|
762
|
+
return m;
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
return 'maybe';
|
|
766
|
+
}
|
|
767
|
+
return 'no';
|
|
768
|
+
}
|
|
769
|
+
// Match a row of a known shape against the split path, the same as
|
|
770
|
+
// #matchGlobstar and #matchGlobStarBodySections do. None of these
|
|
771
|
+
// rows have a drive letter, so they start at the first portion.
|
|
772
|
+
#matchShape(file, row, shape) {
|
|
773
|
+
const dot = !!this.options.dot;
|
|
774
|
+
const n = file.length;
|
|
775
|
+
if (shape === 'head') {
|
|
776
|
+
// x, then at least one portion that ** can walk
|
|
777
|
+
if (n < 2 || !portionMatch(row[0], file[0])) {
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
for (let i = 1; i < n; i++)
|
|
781
|
+
if (!walkable(file[i], dot))
|
|
782
|
+
return false;
|
|
783
|
+
return true;
|
|
784
|
+
}
|
|
785
|
+
const x = row[1];
|
|
786
|
+
if (shape === 'tail') {
|
|
787
|
+
// x is the last portion, or the one before a trailing ''
|
|
788
|
+
let t = n - 1;
|
|
789
|
+
if (!portionMatch(x, file[t])) {
|
|
790
|
+
if (file[t] !== '' || n === 1 || !portionMatch(x, file[--t])) {
|
|
791
|
+
return false;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
for (let i = 0; i < t; i++)
|
|
795
|
+
if (!walkable(file[i], dot))
|
|
796
|
+
return false;
|
|
797
|
+
return true;
|
|
798
|
+
}
|
|
799
|
+
// mid: the first x that ** can walk to, with a portion after it,
|
|
800
|
+
// and ** can walk all of those
|
|
801
|
+
for (let k = 0; k < n; k++) {
|
|
802
|
+
if (portionMatch(x, file[k]) && k + 1 < n) {
|
|
803
|
+
let i = k + 1;
|
|
804
|
+
while (i < n && walkable(file[i], dot))
|
|
805
|
+
i++;
|
|
806
|
+
if (i === n)
|
|
807
|
+
return true;
|
|
808
|
+
}
|
|
809
|
+
if (!walkable(file[k], dot))
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
// Match a row of `**/x/**` or `x/**` against the path, the same as
|
|
815
|
+
// #matchGlobstar and #matchGlobStarBodySections do once it is split.
|
|
816
|
+
// x must match a portion (the first one, for `x/**`), the ** before
|
|
817
|
+
// it must be able to walk the portions before that one, and there
|
|
818
|
+
// must be a portion after it, which the ** after it can walk. At
|
|
819
|
+
// level 2, this is only known if no portion is `.` or `..`.
|
|
820
|
+
#walk(f, row, head, dot, sep) {
|
|
821
|
+
if (this.#level2 && dotPortion(f, 0, f.length, true, sep))
|
|
822
|
+
return 'maybe';
|
|
823
|
+
const x = row[head ? 0 : 1];
|
|
824
|
+
// the last portion has none after it, so it can not be x
|
|
825
|
+
let s = 0;
|
|
826
|
+
for (let e = nextSep(f, s, sep); e !== -1; e = nextSep(f, s, sep)) {
|
|
827
|
+
// the start of the next portion
|
|
828
|
+
let next = e + 1;
|
|
829
|
+
while (next < f.length && isSep(f.charCodeAt(next), sep))
|
|
830
|
+
next++;
|
|
831
|
+
const hit = typeof x === 'string' ?
|
|
832
|
+
e - s === x.length && f.startsWith(x, s)
|
|
833
|
+
: e > s && x.testUnchecked(f.slice(s, e));
|
|
834
|
+
if (hit && !dotPortion(f, next, f.length, dot, sep))
|
|
835
|
+
return 'yes';
|
|
836
|
+
if (head || dotPortion(f, s, next, dot, sep))
|
|
837
|
+
return 'no';
|
|
838
|
+
s = next;
|
|
396
839
|
}
|
|
840
|
+
return 'no';
|
|
841
|
+
}
|
|
842
|
+
// the last split, if it was the same path with the same split
|
|
843
|
+
// settings
|
|
844
|
+
#cachedSplit(f) {
|
|
845
|
+
const last = lastSplit;
|
|
846
|
+
return (last?.f === f &&
|
|
847
|
+
last.isWindows === this.isWindows &&
|
|
848
|
+
last.preserveMultipleSlashes === this.preserveMultipleSlashes &&
|
|
849
|
+
last.normalize === this.#form) ?
|
|
850
|
+
last
|
|
851
|
+
: undefined;
|
|
852
|
+
}
|
|
853
|
+
// split a path for match(), and keep the parts for the next call
|
|
854
|
+
#split(f) {
|
|
855
|
+
const { isWindows, preserveMultipleSlashes } = this;
|
|
856
|
+
// windows: need to use /, not \
|
|
857
|
+
let parts = this.#slashSplit(isWindows ? f.split('\\').join('/') : f);
|
|
858
|
+
// normalize each portion, so that a char that normalizes to `/`
|
|
859
|
+
// does not make a new portion
|
|
860
|
+
const normalize = this.#form;
|
|
861
|
+
if (normalize)
|
|
862
|
+
parts = parts.map(p => p.normalize(normalize));
|
|
863
|
+
lastSplit = {
|
|
864
|
+
f,
|
|
865
|
+
isWindows,
|
|
866
|
+
preserveMultipleSlashes,
|
|
867
|
+
normalize,
|
|
868
|
+
parts,
|
|
869
|
+
};
|
|
870
|
+
return lastSplit;
|
|
871
|
+
}
|
|
872
|
+
// resolve `.` and `..` portions of a path, for level 2
|
|
873
|
+
#levelTwoFileOptimize(file) {
|
|
874
|
+
// work on a copy, so that the cached parts do not change
|
|
875
|
+
const parts = [...file];
|
|
397
876
|
let didSomething = false;
|
|
398
877
|
do {
|
|
399
878
|
didSomething = false;
|
|
@@ -418,17 +897,15 @@ class Minimatch {
|
|
|
418
897
|
}
|
|
419
898
|
}
|
|
420
899
|
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
|
421
|
-
|
|
900
|
+
// .. can not remove the root of a Windows path
|
|
901
|
+
const root = this.#rootIndex(parts) + 1;
|
|
902
|
+
let dd = root;
|
|
422
903
|
while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
|
|
423
904
|
const p = parts[dd - 1];
|
|
424
|
-
if (p &&
|
|
425
|
-
p !== '.' &&
|
|
426
|
-
p !== '..' &&
|
|
427
|
-
p !== '**' &&
|
|
428
|
-
!(this.isWindows && /^[a-z]:$/i.test(p))) {
|
|
905
|
+
if (p && p !== '.' && p !== '..' && p !== '**') {
|
|
429
906
|
didSomething = true;
|
|
430
907
|
parts.splice(dd - 1, 2);
|
|
431
|
-
dd
|
|
908
|
+
dd = Math.max(dd - 2, root);
|
|
432
909
|
}
|
|
433
910
|
}
|
|
434
911
|
} while (didSomething);
|
|
@@ -453,6 +930,8 @@ class Minimatch {
|
|
|
453
930
|
// **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
|
|
454
931
|
// this WOULD be allowed if ** did follow symlinks, or * didn't
|
|
455
932
|
firstPhasePreProcess(globParts) {
|
|
933
|
+
// each **/.. split doubles the patterns, so stop at the brace max
|
|
934
|
+
const { braceExpandMax = 100_000 } = this.options;
|
|
456
935
|
let didSomething = false;
|
|
457
936
|
do {
|
|
458
937
|
didSomething = false;
|
|
@@ -480,7 +959,8 @@ class Minimatch {
|
|
|
480
959
|
p === '..' ||
|
|
481
960
|
!p2 ||
|
|
482
961
|
p2 === '.' ||
|
|
483
|
-
p2 === '..'
|
|
962
|
+
p2 === '..' ||
|
|
963
|
+
globParts.length >= braceExpandMax) {
|
|
484
964
|
continue;
|
|
485
965
|
}
|
|
486
966
|
didSomething = true;
|
|
@@ -512,7 +992,9 @@ class Minimatch {
|
|
|
512
992
|
}
|
|
513
993
|
}
|
|
514
994
|
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
|
515
|
-
|
|
995
|
+
// .. can not remove the root of a Windows path
|
|
996
|
+
const root = this.#rootIndex(parts) + 1;
|
|
997
|
+
let dd = root;
|
|
516
998
|
while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
|
|
517
999
|
const p = parts[dd - 1];
|
|
518
1000
|
if (p && p !== '.' && p !== '..' && p !== '**') {
|
|
@@ -522,7 +1004,7 @@ class Minimatch {
|
|
|
522
1004
|
parts.splice(dd - 1, 2, ...splin);
|
|
523
1005
|
if (parts.length === 0)
|
|
524
1006
|
parts.push('');
|
|
525
|
-
dd
|
|
1007
|
+
dd = Math.max(dd - 2, root);
|
|
526
1008
|
}
|
|
527
1009
|
}
|
|
528
1010
|
}
|
|
@@ -537,6 +1019,10 @@ class Minimatch {
|
|
|
537
1019
|
// {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
|
|
538
1020
|
// ^-- not valid because ** doens't follow symlinks
|
|
539
1021
|
secondPhasePreProcess(globParts) {
|
|
1022
|
+
// each pattern is compared to each other one, so skip this for
|
|
1023
|
+
// large sets. The patterns match the same paths either way.
|
|
1024
|
+
if (globParts.length > 1000)
|
|
1025
|
+
return globParts;
|
|
540
1026
|
for (let i = 0; i < globParts.length - 1; i++) {
|
|
541
1027
|
for (let j = i + 1; j < globParts.length; j++) {
|
|
542
1028
|
const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
|
|
@@ -612,18 +1098,36 @@ class Minimatch {
|
|
|
612
1098
|
this.pattern = pattern.slice(negateOffset);
|
|
613
1099
|
this.negate = negate;
|
|
614
1100
|
}
|
|
615
|
-
//
|
|
616
|
-
//
|
|
617
|
-
//
|
|
618
|
-
//
|
|
619
|
-
//
|
|
620
|
-
|
|
1101
|
+
// Match the parts of a path against one row of the set. `resolved`
|
|
1102
|
+
// is the parts after level 2 resolves `.` and `..` in them, or the
|
|
1103
|
+
// same parts below level 2. Set partial to true to test if, for
|
|
1104
|
+
// example, "/a/b" matches the start of "/*/b/*/d". Partial means, if
|
|
1105
|
+
// you run out of file before you run out of pattern, then that's
|
|
1106
|
+
// fine, as long as all the parts match.
|
|
1107
|
+
#matchRow(file, resolved, pattern, partial) {
|
|
621
1108
|
let fileStartIndex = 0;
|
|
622
1109
|
let patternStartIndex = 0;
|
|
623
|
-
// UNC paths like //?/X:/... can match X:/... and vice versa
|
|
624
|
-
//
|
|
625
|
-
//
|
|
626
|
-
|
|
1110
|
+
// UNC paths like //?/X:/... can match X:/... and vice versa, and
|
|
1111
|
+
// //?/UNC/host/share/... can match //host/share/... and vice versa.
|
|
1112
|
+
// Drive letters in absolute drive or unc paths, and the host and
|
|
1113
|
+
// share of UNC paths, are always compared case-insensitively.
|
|
1114
|
+
const fh = this.isWindows ? uncHost(resolved) : -1;
|
|
1115
|
+
const ph = fh === -1 ? -1 : uncHost(pattern);
|
|
1116
|
+
if (ph !== -1) {
|
|
1117
|
+
const host = pattern[ph];
|
|
1118
|
+
const share = pattern[ph + 1];
|
|
1119
|
+
if (typeof host !== 'string' || typeof share !== 'string') {
|
|
1120
|
+
// a host or share with magic is matched as usual
|
|
1121
|
+
fileStartIndex = fh;
|
|
1122
|
+
patternStartIndex = ph;
|
|
1123
|
+
}
|
|
1124
|
+
else if (resolved[fh].toLowerCase() === host.toLowerCase() &&
|
|
1125
|
+
resolved[fh + 1].toLowerCase() === share.toLowerCase()) {
|
|
1126
|
+
fileStartIndex = fh + 2;
|
|
1127
|
+
patternStartIndex = ph + 2;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
else if (this.isWindows) {
|
|
627
1131
|
const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
|
|
628
1132
|
const fileUNC = !fileDrive &&
|
|
629
1133
|
file[0] === '' &&
|
|
@@ -648,47 +1152,27 @@ class Minimatch {
|
|
|
648
1152
|
file[fdi],
|
|
649
1153
|
pattern[pdi],
|
|
650
1154
|
];
|
|
651
|
-
//
|
|
1155
|
+
// the drives match, so start matching after them
|
|
652
1156
|
if (fd.toLowerCase() === pd.toLowerCase()) {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
fileStartIndex = fdi;
|
|
1157
|
+
patternStartIndex = pdi + 1;
|
|
1158
|
+
fileStartIndex = fdi + 1;
|
|
656
1159
|
}
|
|
657
1160
|
}
|
|
658
1161
|
}
|
|
659
|
-
//
|
|
660
|
-
//
|
|
661
|
-
|
|
662
|
-
if (optimizationLevel >= 2) {
|
|
663
|
-
file = this.levelTwoFileOptimize(file);
|
|
664
|
-
}
|
|
1162
|
+
// the drive letters are found in the parts before level 2 resolves
|
|
1163
|
+
// them, and the match uses the resolved parts
|
|
1164
|
+
file = resolved;
|
|
665
1165
|
if (pattern.includes(exports.GLOBSTAR)) {
|
|
666
1166
|
return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
|
|
667
1167
|
}
|
|
668
1168
|
return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
|
|
669
1169
|
}
|
|
670
1170
|
#matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
|
|
671
|
-
|
|
672
|
-
const firstgs = pattern.indexOf(exports.GLOBSTAR, patternIndex);
|
|
673
|
-
const lastgs = pattern.lastIndexOf(exports.GLOBSTAR);
|
|
674
|
-
// split the pattern up into globstar-delimited sections
|
|
675
|
-
// the tail has to be at the end, and the others just have
|
|
676
|
-
// to be found in order from the head.
|
|
677
|
-
const [head, body, tail] = partial ?
|
|
678
|
-
[
|
|
679
|
-
pattern.slice(patternIndex, firstgs),
|
|
680
|
-
pattern.slice(firstgs + 1),
|
|
681
|
-
[],
|
|
682
|
-
]
|
|
683
|
-
: [
|
|
684
|
-
pattern.slice(patternIndex, firstgs),
|
|
685
|
-
pattern.slice(firstgs + 1, lastgs),
|
|
686
|
-
pattern.slice(lastgs + 1),
|
|
687
|
-
];
|
|
1171
|
+
const { head, body, tail, segments } = this.#getGlobstarParts(pattern, partial, patternIndex);
|
|
688
1172
|
// check the head, from the current file/pattern index.
|
|
689
1173
|
if (head.length) {
|
|
690
|
-
const
|
|
691
|
-
if (!this.#matchOne(
|
|
1174
|
+
const headEnd = fileIndex + head.length;
|
|
1175
|
+
if (!this.#matchOne(file, head, partial, fileIndex, 0, headEnd)) {
|
|
692
1176
|
return false;
|
|
693
1177
|
}
|
|
694
1178
|
fileIndex += head.length;
|
|
@@ -746,36 +1230,64 @@ class Minimatch {
|
|
|
746
1230
|
// now we know that there's one or more body sections, which can
|
|
747
1231
|
// be matched anywhere from the 0 index (because the head was pruned)
|
|
748
1232
|
// through to the length-fileTailMatch index.
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
1233
|
+
return !!this.#matchGlobStarBodySections(file, segments, file.length - fileTailMatch, fileIndex, 0, partial, 0, !!fileTailMatch, new Set());
|
|
1234
|
+
}
|
|
1235
|
+
// Split the pattern into head, tail, and middle of ** delimited
|
|
1236
|
+
// parts. The tail has to be at the end, and the others just have to
|
|
1237
|
+
// be found in order from the head. These only depend on the pattern
|
|
1238
|
+
// row, so they are kept for the next path.
|
|
1239
|
+
#getGlobstarParts(pattern, partial, patternIndex) {
|
|
1240
|
+
let byStart = this.#globstarParts.get(pattern);
|
|
1241
|
+
if (!byStart) {
|
|
1242
|
+
byStart = [];
|
|
1243
|
+
this.#globstarParts.set(pattern, byStart);
|
|
1244
|
+
}
|
|
1245
|
+
const key = patternIndex * 2 + (partial ? 1 : 0);
|
|
1246
|
+
const found = byStart[key];
|
|
1247
|
+
if (found)
|
|
1248
|
+
return found;
|
|
1249
|
+
const firstgs = pattern.indexOf(exports.GLOBSTAR, patternIndex);
|
|
1250
|
+
const lastgs = pattern.lastIndexOf(exports.GLOBSTAR);
|
|
1251
|
+
const head = pattern.slice(patternIndex, firstgs);
|
|
1252
|
+
const body = pattern.slice(firstgs + 1, partial ? undefined : lastgs);
|
|
1253
|
+
const tail = partial ? [] : pattern.slice(lastgs + 1);
|
|
1254
|
+
// split the body up into sections, and note the number of
|
|
1255
|
+
// portions that must come after the start of each one
|
|
1256
|
+
const segments = [[[], 0]];
|
|
1257
|
+
let current = segments[0];
|
|
754
1258
|
let nonGsParts = 0;
|
|
755
1259
|
const nonGsPartsSums = [0];
|
|
756
1260
|
for (const b of body) {
|
|
757
1261
|
if (b === exports.GLOBSTAR) {
|
|
758
1262
|
nonGsPartsSums.push(nonGsParts);
|
|
759
|
-
|
|
760
|
-
|
|
1263
|
+
current = [[], 0];
|
|
1264
|
+
segments.push(current);
|
|
761
1265
|
}
|
|
762
1266
|
else {
|
|
763
|
-
|
|
1267
|
+
current[0].push(b);
|
|
764
1268
|
nonGsParts++;
|
|
765
1269
|
}
|
|
766
1270
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
}
|
|
772
|
-
|
|
1271
|
+
// the portions in this section and the ones after it
|
|
1272
|
+
segments.forEach((b, i) => {
|
|
1273
|
+
b[1] = nonGsParts - nonGsPartsSums[i];
|
|
1274
|
+
});
|
|
1275
|
+
const parts = { head, body, tail, segments };
|
|
1276
|
+
byStart[key] = parts;
|
|
1277
|
+
return parts;
|
|
773
1278
|
}
|
|
774
1279
|
// return false for "nope, not matching"
|
|
775
1280
|
// return null for "not matching, cannot keep trying"
|
|
776
1281
|
#matchGlobStarBodySections(file,
|
|
777
|
-
// pattern section,
|
|
778
|
-
bodySegments,
|
|
1282
|
+
// pattern section, and the portions that it and the rest need
|
|
1283
|
+
bodySegments,
|
|
1284
|
+
// the end of the file portions that the body can match
|
|
1285
|
+
fileLength, fileIndex, bodyIndex, partial, globStarDepth, sawTail,
|
|
1286
|
+
// the places that a walk has already tried, as
|
|
1287
|
+
// bodyIndex * (file.length + 1) + fileIndex. A walk from a place
|
|
1288
|
+
// does the same no matter how it got there, and it only comes back
|
|
1289
|
+
// if it found no match, so a walk that gets to one stops.
|
|
1290
|
+
tried) {
|
|
779
1291
|
// take the first body segment, and walk from fileIndex to its "after"
|
|
780
1292
|
// value at the end
|
|
781
1293
|
// If it doesn't match at that position, we increment, until we hit
|
|
@@ -787,8 +1299,16 @@ class Minimatch {
|
|
|
787
1299
|
// can't possibly be a valid matching condition.
|
|
788
1300
|
const bs = bodySegments[bodyIndex];
|
|
789
1301
|
if (!bs) {
|
|
790
|
-
//
|
|
791
|
-
|
|
1302
|
+
// with partial, the body is the rest of the pattern, so it
|
|
1303
|
+
// matches if no portions are left, or only the '' of a trailing
|
|
1304
|
+
// / (as a/* matches a/b/). A ** at the end walks them as its own
|
|
1305
|
+
// empty section.
|
|
1306
|
+
if (partial) {
|
|
1307
|
+
return (fileIndex >= fileLength ||
|
|
1308
|
+
(fileIndex === fileLength - 1 && file[fileIndex] === ''));
|
|
1309
|
+
}
|
|
1310
|
+
// just make sure that there's no bad dots before the tail
|
|
1311
|
+
for (let i = fileIndex; i < fileLength; i++) {
|
|
792
1312
|
sawTail = true;
|
|
793
1313
|
const f = file[i];
|
|
794
1314
|
if (f === '.' ||
|
|
@@ -799,19 +1319,29 @@ class Minimatch {
|
|
|
799
1319
|
}
|
|
800
1320
|
return sawTail;
|
|
801
1321
|
}
|
|
802
|
-
// have a non-globstar body section to test
|
|
803
|
-
|
|
1322
|
+
// have a non-globstar body section to test, up to the last index
|
|
1323
|
+
// where it can start
|
|
1324
|
+
const [body, need] = bs;
|
|
1325
|
+
// with partial, the path can end before the body does
|
|
1326
|
+
const after = partial ? fileLength : fileLength - need;
|
|
804
1327
|
while (fileIndex <= after) {
|
|
805
|
-
const
|
|
1328
|
+
const key = bodyIndex * (file.length + 1) + fileIndex;
|
|
1329
|
+
if (tried.has(key))
|
|
1330
|
+
return false;
|
|
1331
|
+
tried.add(key);
|
|
1332
|
+
const m = this.#matchOne(file, body, partial, fileIndex, 0, fileIndex + body.length);
|
|
806
1333
|
// if limit exceeded, no match. intentional false negative,
|
|
807
1334
|
// acceptable break in correctness for security.
|
|
808
1335
|
if (m && globStarDepth < this.maxGlobstarRecursion) {
|
|
809
1336
|
// match! see if the rest match. if so, we're done!
|
|
810
|
-
const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
|
|
1337
|
+
const sub = this.#matchGlobStarBodySections(file, bodySegments, fileLength, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail, tried);
|
|
811
1338
|
if (sub !== false) {
|
|
812
1339
|
return sub;
|
|
813
1340
|
}
|
|
814
1341
|
}
|
|
1342
|
+
// the ** does not walk past the last place the body can start
|
|
1343
|
+
if (fileIndex === after)
|
|
1344
|
+
break;
|
|
815
1345
|
const f = file[fileIndex];
|
|
816
1346
|
if (f === '.' ||
|
|
817
1347
|
f === '..' ||
|
|
@@ -823,21 +1353,20 @@ class Minimatch {
|
|
|
823
1353
|
// walked off. no point continuing
|
|
824
1354
|
return partial || null;
|
|
825
1355
|
}
|
|
826
|
-
#matchOne(file, pattern, partial, fileIndex, patternIndex
|
|
1356
|
+
#matchOne(file, pattern, partial, fileIndex, patternIndex,
|
|
1357
|
+
// only match the file portions before this index
|
|
1358
|
+
fileEnd = file.length) {
|
|
827
1359
|
let fi;
|
|
828
1360
|
let pi;
|
|
829
1361
|
let pl;
|
|
830
1362
|
let fl;
|
|
831
1363
|
for (fi = fileIndex,
|
|
832
1364
|
pi = patternIndex,
|
|
833
|
-
fl = file.length,
|
|
1365
|
+
fl = Math.min(fileEnd, file.length),
|
|
834
1366
|
pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
|
|
835
|
-
this.debug('matchOne loop');
|
|
836
1367
|
let p = pattern[pi];
|
|
837
1368
|
let f = file[fi];
|
|
838
|
-
this.debug(pattern, p, f);
|
|
839
1369
|
// should be impossible.
|
|
840
|
-
// some invalid regexp stuff in the set.
|
|
841
1370
|
/* c8 ignore start */
|
|
842
1371
|
if (p === false || p === exports.GLOBSTAR) {
|
|
843
1372
|
return false;
|
|
@@ -845,17 +1374,8 @@ class Minimatch {
|
|
|
845
1374
|
/* c8 ignore stop */
|
|
846
1375
|
// something other than **
|
|
847
1376
|
// non-magic patterns just have to match exactly
|
|
848
|
-
// patterns with magic have been turned into
|
|
849
|
-
|
|
850
|
-
if (typeof p === 'string') {
|
|
851
|
-
hit = f === p;
|
|
852
|
-
this.debug('string match', p, f, hit);
|
|
853
|
-
}
|
|
854
|
-
else {
|
|
855
|
-
hit = p.test(f);
|
|
856
|
-
this.debug('pattern match', p, f, hit);
|
|
857
|
-
}
|
|
858
|
-
if (!hit)
|
|
1377
|
+
// patterns with magic have been turned into Matchers.
|
|
1378
|
+
if (!portionMatch(p, f))
|
|
859
1379
|
return false;
|
|
860
1380
|
}
|
|
861
1381
|
// Note: ending in / means that we'll get a final ""
|
|
@@ -864,9 +1384,8 @@ class Minimatch {
|
|
|
864
1384
|
// If the file ends in /, then it can only match a
|
|
865
1385
|
// a pattern that ends in /, unless the pattern just
|
|
866
1386
|
// doesn't have any more for it. But, a/b/ should *not*
|
|
867
|
-
// match "a/b/*", even though ""
|
|
868
|
-
//
|
|
869
|
-
// simply not be reached yet.
|
|
1387
|
+
// match "a/b/*", even though * can match "", except in
|
|
1388
|
+
// partial mode, where it might simply not be reached yet.
|
|
870
1389
|
// However, a/b/ should still satisfy a/*
|
|
871
1390
|
// now either we fell off the end of the pattern, or we're done.
|
|
872
1391
|
if (fi === fl && pi === pl) {
|
|
@@ -905,139 +1424,26 @@ class Minimatch {
|
|
|
905
1424
|
return exports.GLOBSTAR;
|
|
906
1425
|
if (pattern === '')
|
|
907
1426
|
return '';
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
if (
|
|
913
|
-
|
|
1427
|
+
const { nocase, nocaseMagicOnly, noext = false, dot, normalize, } = options;
|
|
1428
|
+
const lit = literal(pattern, noext);
|
|
1429
|
+
// in nocase mode, a literal with cased chars still needs a
|
|
1430
|
+
// Matcher, unless nocaseMagicOnly is set.
|
|
1431
|
+
if (lit !== undefined &&
|
|
1432
|
+
!(nocase &&
|
|
1433
|
+
!nocaseMagicOnly &&
|
|
1434
|
+
pattern.toUpperCase() !== pattern.toLowerCase())) {
|
|
1435
|
+
return this.#norm(lit);
|
|
914
1436
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
: starDotExtTest)(m[1]);
|
|
1437
|
+
if (this.#pending)
|
|
1438
|
+
return PENDING;
|
|
1439
|
+
let m = this.#matchers.get(pattern);
|
|
1440
|
+
if (!m) {
|
|
1441
|
+
m = new nonrecursive_glob_match_1.Matcher(pattern, { nocase, noext, dot, normalize });
|
|
1442
|
+
this.#matchers.set(pattern, m);
|
|
922
1443
|
}
|
|
923
|
-
|
|
924
|
-
fastTest = (options.nocase ?
|
|
925
|
-
options.dot ?
|
|
926
|
-
qmarksTestNocaseDot
|
|
927
|
-
: qmarksTestNocase
|
|
928
|
-
: options.dot ? qmarksTestDot
|
|
929
|
-
: qmarksTest)(m);
|
|
930
|
-
}
|
|
931
|
-
else if ((m = pattern.match(starDotStarRE))) {
|
|
932
|
-
fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
|
|
933
|
-
}
|
|
934
|
-
else if ((m = pattern.match(dotStarRE))) {
|
|
935
|
-
fastTest = dotStarTest;
|
|
936
|
-
}
|
|
937
|
-
const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern();
|
|
938
|
-
if (fastTest && typeof re === 'object') {
|
|
939
|
-
// Avoids overriding in frozen environments
|
|
940
|
-
Reflect.defineProperty(re, 'test', { value: fastTest });
|
|
941
|
-
}
|
|
942
|
-
return re;
|
|
1444
|
+
return m;
|
|
943
1445
|
}
|
|
944
|
-
|
|
945
|
-
if (this.regexp || this.regexp === false)
|
|
946
|
-
return this.regexp;
|
|
947
|
-
// at this point, this.set is a 2d array of partial
|
|
948
|
-
// pattern strings, or "**".
|
|
949
|
-
//
|
|
950
|
-
// It's better to use .match(). This function shouldn't
|
|
951
|
-
// be used, really, but it's pretty convenient sometimes,
|
|
952
|
-
// when you just want to work with a regex.
|
|
953
|
-
const set = this.set;
|
|
954
|
-
if (!set.length) {
|
|
955
|
-
this.regexp = false;
|
|
956
|
-
return this.regexp;
|
|
957
|
-
}
|
|
958
|
-
const options = this.options;
|
|
959
|
-
const twoStar = options.noglobstar ? star
|
|
960
|
-
: options.dot ? twoStarDot
|
|
961
|
-
: twoStarNoDot;
|
|
962
|
-
const flags = new Set(options.nocase ? ['i'] : []);
|
|
963
|
-
// regexpify non-globstar patterns
|
|
964
|
-
// if ** is only item, then we just do one twoStar
|
|
965
|
-
// if ** is first, and there are more, prepend (\/|twoStar\/)? to next
|
|
966
|
-
// if ** is last, append (\/twoStar|) to previous
|
|
967
|
-
// if ** is in the middle, append (\/|\/twoStar\/) to previous
|
|
968
|
-
// then filter out GLOBSTAR symbols
|
|
969
|
-
let re = set
|
|
970
|
-
.map(pattern => {
|
|
971
|
-
const pp = pattern.map(p => {
|
|
972
|
-
if (p instanceof RegExp) {
|
|
973
|
-
for (const f of p.flags.split(''))
|
|
974
|
-
flags.add(f);
|
|
975
|
-
}
|
|
976
|
-
return (typeof p === 'string' ? regExpEscape(p)
|
|
977
|
-
: p === exports.GLOBSTAR ? exports.GLOBSTAR
|
|
978
|
-
: p._src);
|
|
979
|
-
});
|
|
980
|
-
pp.forEach((p, i) => {
|
|
981
|
-
const next = pp[i + 1];
|
|
982
|
-
const prev = pp[i - 1];
|
|
983
|
-
if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) {
|
|
984
|
-
return;
|
|
985
|
-
}
|
|
986
|
-
if (prev === undefined) {
|
|
987
|
-
if (next !== undefined && next !== exports.GLOBSTAR) {
|
|
988
|
-
pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
|
|
989
|
-
}
|
|
990
|
-
else {
|
|
991
|
-
pp[i] = twoStar;
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
else if (next === undefined) {
|
|
995
|
-
pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + ')?';
|
|
996
|
-
}
|
|
997
|
-
else if (next !== exports.GLOBSTAR) {
|
|
998
|
-
pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
|
|
999
|
-
pp[i + 1] = exports.GLOBSTAR;
|
|
1000
|
-
}
|
|
1001
|
-
});
|
|
1002
|
-
const filtered = pp.filter(p => p !== exports.GLOBSTAR);
|
|
1003
|
-
// For partial matches, we need to make the pattern match
|
|
1004
|
-
// any prefix of the full path. We do this by generating
|
|
1005
|
-
// alternative patterns that match progressively longer prefixes.
|
|
1006
|
-
if (this.partial && filtered.length >= 1) {
|
|
1007
|
-
const prefixes = [];
|
|
1008
|
-
for (let i = 1; i <= filtered.length; i++) {
|
|
1009
|
-
prefixes.push(filtered.slice(0, i).join('/'));
|
|
1010
|
-
}
|
|
1011
|
-
return '(?:' + prefixes.join('|') + ')';
|
|
1012
|
-
}
|
|
1013
|
-
return filtered.join('/');
|
|
1014
|
-
})
|
|
1015
|
-
.join('|');
|
|
1016
|
-
// need to wrap in parens if we had more than one thing with |,
|
|
1017
|
-
// otherwise only the first will be anchored to ^ and the last to $
|
|
1018
|
-
const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
|
|
1019
|
-
// must match entire pattern
|
|
1020
|
-
// ending in a * or ** will make it less strict.
|
|
1021
|
-
re = '^' + open + re + close + '$';
|
|
1022
|
-
// In partial mode, '/' should always match as it's a valid prefix for any pattern
|
|
1023
|
-
if (this.partial) {
|
|
1024
|
-
re = '^(?:\\/|' + open + re.slice(1, -1) + close + ')$';
|
|
1025
|
-
}
|
|
1026
|
-
// can match anything, as long as it's not this.
|
|
1027
|
-
if (this.negate)
|
|
1028
|
-
re = '^(?!' + re + ').+$';
|
|
1029
|
-
try {
|
|
1030
|
-
this.regexp = new RegExp(re, [...flags].join(''));
|
|
1031
|
-
/* c8 ignore start */
|
|
1032
|
-
}
|
|
1033
|
-
catch {
|
|
1034
|
-
// should be impossible
|
|
1035
|
-
this.regexp = false;
|
|
1036
|
-
}
|
|
1037
|
-
/* c8 ignore stop */
|
|
1038
|
-
return this.regexp;
|
|
1039
|
-
}
|
|
1040
|
-
slashSplit(p) {
|
|
1446
|
+
#slashSplit(p) {
|
|
1041
1447
|
// if p starts with // on windows, we preserve that
|
|
1042
1448
|
// so that UNC paths aren't broken. Otherwise, any number of
|
|
1043
1449
|
// / characters are coalesced into one, unless
|
|
@@ -1054,7 +1460,6 @@ class Minimatch {
|
|
|
1054
1460
|
}
|
|
1055
1461
|
}
|
|
1056
1462
|
match(f, partial = this.partial) {
|
|
1057
|
-
this.debug('match', f, this.pattern);
|
|
1058
1463
|
// short-circuit in the case of busted things.
|
|
1059
1464
|
// comments, etc.
|
|
1060
1465
|
if (this.comment) {
|
|
@@ -1067,19 +1472,36 @@ class Minimatch {
|
|
|
1067
1472
|
return true;
|
|
1068
1473
|
}
|
|
1069
1474
|
const options = this.options;
|
|
1070
|
-
//
|
|
1071
|
-
|
|
1072
|
-
|
|
1475
|
+
// treat the test path as a set of pathparts. If it was not just
|
|
1476
|
+
// split or checked, check that it can match before splitting it.
|
|
1477
|
+
let split = this.#cachedSplit(f);
|
|
1478
|
+
if (!split) {
|
|
1479
|
+
// the checks look at the path as given, so not if it is
|
|
1480
|
+
// normalized
|
|
1481
|
+
if (!partial &&
|
|
1482
|
+
!this.#form &&
|
|
1483
|
+
(this.#endCheck || this.#literalCheck) &&
|
|
1484
|
+
lastChecked !== f) {
|
|
1485
|
+
lastChecked = f;
|
|
1486
|
+
const can = this.#canMatch(f);
|
|
1487
|
+
if (can === 'no')
|
|
1488
|
+
return options.flipNegate ? false : this.negate;
|
|
1489
|
+
if (can === 'yes')
|
|
1490
|
+
return options.flipNegate ? true : !this.negate;
|
|
1491
|
+
}
|
|
1492
|
+
split = this.#split(f);
|
|
1073
1493
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1494
|
+
const ff = split.parts;
|
|
1495
|
+
// the parts after level 2 resolves them, kept for the next pattern
|
|
1496
|
+
// that tests the same path
|
|
1497
|
+
const resolved = this.#level2 ?
|
|
1498
|
+
(split.resolved ??= this.#levelTwoFileOptimize(ff))
|
|
1499
|
+
: ff;
|
|
1077
1500
|
// just ONE of the pattern sets in this.set needs to match
|
|
1078
1501
|
// in order for it to be valid. If negating, then just one
|
|
1079
1502
|
// match means that we have failed.
|
|
1080
1503
|
// Either way, return on the first hit.
|
|
1081
1504
|
const set = this.set;
|
|
1082
|
-
this.debug(this.pattern, 'set', set);
|
|
1083
1505
|
// Find the basename of the path by looking for the last non-empty segment
|
|
1084
1506
|
let filename = ff[ff.length - 1];
|
|
1085
1507
|
if (!filename) {
|
|
@@ -1087,12 +1509,16 @@ class Minimatch {
|
|
|
1087
1509
|
filename = ff[i];
|
|
1088
1510
|
}
|
|
1089
1511
|
}
|
|
1090
|
-
for (
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1512
|
+
for (let r = 0; r < set.length; r++) {
|
|
1513
|
+
const pattern = set[r];
|
|
1514
|
+
const shape = partial ? undefined : this.#shapes[r];
|
|
1515
|
+
// level 2 does not change a path of one portion
|
|
1516
|
+
const hit = shape === 'base' ?
|
|
1517
|
+
portionMatch(pattern[0], filename)
|
|
1518
|
+
: shape ? this.#matchShape(resolved, pattern, shape)
|
|
1519
|
+
: options.matchBase && pattern.length === 1 ?
|
|
1520
|
+
this.#matchRow([filename], [filename], pattern, partial)
|
|
1521
|
+
: this.#matchRow(ff, resolved, pattern, partial);
|
|
1096
1522
|
if (hit) {
|
|
1097
1523
|
if (options.flipNegate) {
|
|
1098
1524
|
return true;
|
|
@@ -1113,14 +1539,11 @@ class Minimatch {
|
|
|
1113
1539
|
}
|
|
1114
1540
|
exports.Minimatch = Minimatch;
|
|
1115
1541
|
/* c8 ignore start */
|
|
1116
|
-
var ast_js_2 = require("./ast.js");
|
|
1117
|
-
Object.defineProperty(exports, "AST", { enumerable: true, get: function () { return ast_js_2.AST; } });
|
|
1118
1542
|
var escape_js_2 = require("./escape.js");
|
|
1119
1543
|
Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } });
|
|
1120
1544
|
var unescape_js_2 = require("./unescape.js");
|
|
1121
1545
|
Object.defineProperty(exports, "unescape", { enumerable: true, get: function () { return unescape_js_2.unescape; } });
|
|
1122
1546
|
/* c8 ignore stop */
|
|
1123
|
-
exports.minimatch.AST = ast_js_1.AST;
|
|
1124
1547
|
exports.minimatch.Minimatch = Minimatch;
|
|
1125
1548
|
exports.minimatch.escape = escape_js_1.escape;
|
|
1126
1549
|
exports.minimatch.unescape = unescape_js_1.unescape;
|