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