minimatch 3.1.2 → 5.1.0
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/LICENSE +1 -1
- package/README.md +34 -5
- package/lib/path.js +4 -0
- package/minimatch.js +738 -779
- package/package.json +7 -8
package/minimatch.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
module.exports =
|
|
2
|
-
|
|
1
|
+
const minimatch = module.exports = (p, pattern, options = {}) => {
|
|
2
|
+
assertValidPattern(pattern)
|
|
3
|
+
|
|
4
|
+
// shortcut: comments match nothing.
|
|
5
|
+
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
6
|
+
return false
|
|
7
|
+
}
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
sep: '/'
|
|
9
|
+
return new Minimatch(pattern, options).match(p)
|
|
6
10
|
}
|
|
11
|
+
|
|
12
|
+
module.exports = minimatch
|
|
13
|
+
|
|
14
|
+
const path = require('./lib/path.js')
|
|
7
15
|
minimatch.sep = path.sep
|
|
8
16
|
|
|
9
|
-
|
|
10
|
-
|
|
17
|
+
const GLOBSTAR = Symbol('globstar **')
|
|
18
|
+
minimatch.GLOBSTAR = GLOBSTAR
|
|
19
|
+
const expand = require('brace-expansion')
|
|
11
20
|
|
|
12
|
-
|
|
21
|
+
const plTypes = {
|
|
13
22
|
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
|
|
14
23
|
'?': { open: '(?:', close: ')?' },
|
|
15
24
|
'+': { open: '(?:', close: ')+' },
|
|
@@ -19,215 +28,71 @@ var plTypes = {
|
|
|
19
28
|
|
|
20
29
|
// any single thing other than /
|
|
21
30
|
// don't need to escape / when using new RegExp()
|
|
22
|
-
|
|
31
|
+
const qmark = '[^/]'
|
|
23
32
|
|
|
24
33
|
// * => any number of characters
|
|
25
|
-
|
|
34
|
+
const star = qmark + '*?'
|
|
26
35
|
|
|
27
36
|
// ** when dots are allowed. Anything goes, except .. and .
|
|
28
37
|
// not (^ or / followed by one or two dots followed by $ or /),
|
|
29
38
|
// followed by anything, any number of times.
|
|
30
|
-
|
|
39
|
+
const twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
|
|
31
40
|
|
|
32
41
|
// not a ^ or / followed by a dot,
|
|
33
42
|
// followed by anything, any number of times.
|
|
34
|
-
|
|
43
|
+
const twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
|
|
44
|
+
|
|
45
|
+
// "abc" -> { a:true, b:true, c:true }
|
|
46
|
+
const charSet = s => s.split('').reduce((set, c) => {
|
|
47
|
+
set[c] = true
|
|
48
|
+
return set
|
|
49
|
+
}, {})
|
|
35
50
|
|
|
36
51
|
// characters that need to be escaped in RegExp.
|
|
37
|
-
|
|
52
|
+
const reSpecials = charSet('().*{}+?[]^$\\!')
|
|
38
53
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
return s.split('').reduce(function (set, c) {
|
|
42
|
-
set[c] = true
|
|
43
|
-
return set
|
|
44
|
-
}, {})
|
|
45
|
-
}
|
|
54
|
+
// characters that indicate we have to add the pattern start
|
|
55
|
+
const addPatternStartSet = charSet('[.(')
|
|
46
56
|
|
|
47
57
|
// normalizes slashes.
|
|
48
|
-
|
|
58
|
+
const slashSplit = /\/+/
|
|
49
59
|
|
|
50
|
-
minimatch.filter =
|
|
51
|
-
|
|
52
|
-
options = options || {}
|
|
53
|
-
return function (p, i, list) {
|
|
54
|
-
return minimatch(p, pattern, options)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
60
|
+
minimatch.filter = (pattern, options = {}) =>
|
|
61
|
+
(p, i, list) => minimatch(p, pattern, options)
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Object.keys(
|
|
62
|
-
t[k] = a[k]
|
|
63
|
-
})
|
|
64
|
-
Object.keys(b).forEach(function (k) {
|
|
65
|
-
t[k] = b[k]
|
|
66
|
-
})
|
|
63
|
+
const ext = (a, b = {}) => {
|
|
64
|
+
const t = {}
|
|
65
|
+
Object.keys(a).forEach(k => t[k] = a[k])
|
|
66
|
+
Object.keys(b).forEach(k => t[k] = b[k])
|
|
67
67
|
return t
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
minimatch.defaults =
|
|
70
|
+
minimatch.defaults = def => {
|
|
71
71
|
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
|
|
72
72
|
return minimatch
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
var m = function minimatch (p, pattern, options) {
|
|
78
|
-
return orig(p, pattern, ext(def, options))
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
m.Minimatch = function Minimatch (pattern, options) {
|
|
82
|
-
return new orig.Minimatch(pattern, ext(def, options))
|
|
83
|
-
}
|
|
84
|
-
m.Minimatch.defaults = function defaults (options) {
|
|
85
|
-
return orig.defaults(ext(def, options)).Minimatch
|
|
86
|
-
}
|
|
75
|
+
const orig = minimatch
|
|
87
76
|
|
|
88
|
-
m
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return orig.defaults(ext(def, options))
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
m.makeRe = function makeRe (pattern, options) {
|
|
97
|
-
return orig.makeRe(pattern, ext(def, options))
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
m.braceExpand = function braceExpand (pattern, options) {
|
|
101
|
-
return orig.braceExpand(pattern, ext(def, options))
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
m.match = function (list, pattern, options) {
|
|
105
|
-
return orig.match(list, pattern, ext(def, options))
|
|
77
|
+
const m = (p, pattern, options) => orig(p, pattern, ext(def, options))
|
|
78
|
+
m.Minimatch = class Minimatch extends orig.Minimatch {
|
|
79
|
+
constructor (pattern, options) {
|
|
80
|
+
super(pattern, ext(def, options))
|
|
81
|
+
}
|
|
106
82
|
}
|
|
83
|
+
m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch
|
|
84
|
+
m.filter = (pattern, options) => orig.filter(pattern, ext(def, options))
|
|
85
|
+
m.defaults = options => orig.defaults(ext(def, options))
|
|
86
|
+
m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options))
|
|
87
|
+
m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options))
|
|
88
|
+
m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options))
|
|
107
89
|
|
|
108
90
|
return m
|
|
109
91
|
}
|
|
110
92
|
|
|
111
|
-
Minimatch.defaults = function (def) {
|
|
112
|
-
return minimatch.defaults(def).Minimatch
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function minimatch (p, pattern, options) {
|
|
116
|
-
assertValidPattern(pattern)
|
|
117
|
-
|
|
118
|
-
if (!options) options = {}
|
|
119
|
-
|
|
120
|
-
// shortcut: comments match nothing.
|
|
121
|
-
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
122
|
-
return false
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return new Minimatch(pattern, options).match(p)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function Minimatch (pattern, options) {
|
|
129
|
-
if (!(this instanceof Minimatch)) {
|
|
130
|
-
return new Minimatch(pattern, options)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
assertValidPattern(pattern)
|
|
134
|
-
|
|
135
|
-
if (!options) options = {}
|
|
136
|
-
|
|
137
|
-
pattern = pattern.trim()
|
|
138
|
-
|
|
139
|
-
// windows support: need to use /, not \
|
|
140
|
-
if (!options.allowWindowsEscape && path.sep !== '/') {
|
|
141
|
-
pattern = pattern.split(path.sep).join('/')
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
this.options = options
|
|
145
|
-
this.set = []
|
|
146
|
-
this.pattern = pattern
|
|
147
|
-
this.regexp = null
|
|
148
|
-
this.negate = false
|
|
149
|
-
this.comment = false
|
|
150
|
-
this.empty = false
|
|
151
|
-
this.partial = !!options.partial
|
|
152
|
-
|
|
153
|
-
// make the set of regexps etc.
|
|
154
|
-
this.make()
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
Minimatch.prototype.debug = function () {}
|
|
158
|
-
|
|
159
|
-
Minimatch.prototype.make = make
|
|
160
|
-
function make () {
|
|
161
|
-
var pattern = this.pattern
|
|
162
|
-
var options = this.options
|
|
163
|
-
|
|
164
|
-
// empty patterns and comments match nothing.
|
|
165
|
-
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
166
|
-
this.comment = true
|
|
167
|
-
return
|
|
168
|
-
}
|
|
169
|
-
if (!pattern) {
|
|
170
|
-
this.empty = true
|
|
171
|
-
return
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// step 1: figure out negation, etc.
|
|
175
|
-
this.parseNegate()
|
|
176
|
-
|
|
177
|
-
// step 2: expand braces
|
|
178
|
-
var set = this.globSet = this.braceExpand()
|
|
179
|
-
|
|
180
|
-
if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
|
|
181
|
-
|
|
182
|
-
this.debug(this.pattern, set)
|
|
183
|
-
|
|
184
|
-
// step 3: now we have a set, so turn each one into a series of path-portion
|
|
185
|
-
// matching patterns.
|
|
186
|
-
// These will be regexps, except in the case of "**", which is
|
|
187
|
-
// set to the GLOBSTAR object for globstar behavior,
|
|
188
|
-
// and will not contain any / characters
|
|
189
|
-
set = this.globParts = set.map(function (s) {
|
|
190
|
-
return s.split(slashSplit)
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
this.debug(this.pattern, set)
|
|
194
|
-
|
|
195
|
-
// glob --> regexps
|
|
196
|
-
set = set.map(function (s, si, set) {
|
|
197
|
-
return s.map(this.parse, this)
|
|
198
|
-
}, this)
|
|
199
|
-
|
|
200
|
-
this.debug(this.pattern, set)
|
|
201
|
-
|
|
202
|
-
// filter out everything that didn't compile properly.
|
|
203
|
-
set = set.filter(function (s) {
|
|
204
|
-
return s.indexOf(false) === -1
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
this.debug(this.pattern, set)
|
|
208
|
-
|
|
209
|
-
this.set = set
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
Minimatch.prototype.parseNegate = parseNegate
|
|
213
|
-
function parseNegate () {
|
|
214
|
-
var pattern = this.pattern
|
|
215
|
-
var negate = false
|
|
216
|
-
var options = this.options
|
|
217
|
-
var negateOffset = 0
|
|
218
93
|
|
|
219
|
-
if (options.nonegate) return
|
|
220
94
|
|
|
221
|
-
for (var i = 0, l = pattern.length
|
|
222
|
-
; i < l && pattern.charAt(i) === '!'
|
|
223
|
-
; i++) {
|
|
224
|
-
negate = !negate
|
|
225
|
-
negateOffset++
|
|
226
|
-
}
|
|
227
95
|
|
|
228
|
-
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
|
229
|
-
this.negate = negate
|
|
230
|
-
}
|
|
231
96
|
|
|
232
97
|
// Brace expansion:
|
|
233
98
|
// a{b,c}d -> abd acd
|
|
@@ -239,24 +104,9 @@ function parseNegate () {
|
|
|
239
104
|
// Invalid sets are not expanded.
|
|
240
105
|
// a{2..}b -> a{2..}b
|
|
241
106
|
// a{b}c -> a{b}c
|
|
242
|
-
minimatch.braceExpand =
|
|
243
|
-
return braceExpand(pattern, options)
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
Minimatch.prototype.braceExpand = braceExpand
|
|
247
|
-
|
|
248
|
-
function braceExpand (pattern, options) {
|
|
249
|
-
if (!options) {
|
|
250
|
-
if (this instanceof Minimatch) {
|
|
251
|
-
options = this.options
|
|
252
|
-
} else {
|
|
253
|
-
options = {}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
pattern = typeof pattern === 'undefined'
|
|
258
|
-
? this.pattern : pattern
|
|
107
|
+
minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options)
|
|
259
108
|
|
|
109
|
+
const braceExpand = (pattern, options = {}) => {
|
|
260
110
|
assertValidPattern(pattern)
|
|
261
111
|
|
|
262
112
|
// Thanks to Yeting Li <https://github.com/yetingli> for
|
|
@@ -269,8 +119,8 @@ function braceExpand (pattern, options) {
|
|
|
269
119
|
return expand(pattern)
|
|
270
120
|
}
|
|
271
121
|
|
|
272
|
-
|
|
273
|
-
|
|
122
|
+
const MAX_PATTERN_LENGTH = 1024 * 64
|
|
123
|
+
const assertValidPattern = pattern => {
|
|
274
124
|
if (typeof pattern !== 'string') {
|
|
275
125
|
throw new TypeError('invalid pattern')
|
|
276
126
|
}
|
|
@@ -291,657 +141,766 @@ var assertValidPattern = function (pattern) {
|
|
|
291
141
|
// when it is the *only* thing in a path portion. Otherwise, any series
|
|
292
142
|
// of * is equivalent to a single *. Globstar behavior is enabled by
|
|
293
143
|
// default, and can be disabled by setting options.noglobstar.
|
|
294
|
-
|
|
295
|
-
var SUBPARSE = {}
|
|
296
|
-
function parse (pattern, isSub) {
|
|
297
|
-
assertValidPattern(pattern)
|
|
144
|
+
const SUBPARSE = Symbol('subparse')
|
|
298
145
|
|
|
299
|
-
|
|
146
|
+
minimatch.makeRe = (pattern, options) =>
|
|
147
|
+
new Minimatch(pattern, options || {}).makeRe()
|
|
300
148
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
pattern = '*'
|
|
149
|
+
minimatch.match = (list, pattern, options = {}) => {
|
|
150
|
+
const mm = new Minimatch(pattern, options)
|
|
151
|
+
list = list.filter(f => mm.match(f))
|
|
152
|
+
if (mm.options.nonull && !list.length) {
|
|
153
|
+
list.push(pattern)
|
|
307
154
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
function clearStateChar () {
|
|
329
|
-
if (stateChar) {
|
|
330
|
-
// we had some state-tracking character
|
|
331
|
-
// that wasn't consumed by this pass.
|
|
332
|
-
switch (stateChar) {
|
|
333
|
-
case '*':
|
|
334
|
-
re += star
|
|
335
|
-
hasMagic = true
|
|
336
|
-
break
|
|
337
|
-
case '?':
|
|
338
|
-
re += qmark
|
|
339
|
-
hasMagic = true
|
|
340
|
-
break
|
|
341
|
-
default:
|
|
342
|
-
re += '\\' + stateChar
|
|
343
|
-
break
|
|
344
|
-
}
|
|
345
|
-
self.debug('clearStateChar %j %j', stateChar, re)
|
|
346
|
-
stateChar = false
|
|
155
|
+
return list
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// replace stuff like \* with *
|
|
159
|
+
const globUnescape = s => s.replace(/\\(.)/g, '$1')
|
|
160
|
+
const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
|
161
|
+
|
|
162
|
+
class Minimatch {
|
|
163
|
+
constructor (pattern, options) {
|
|
164
|
+
assertValidPattern(pattern)
|
|
165
|
+
|
|
166
|
+
if (!options) options = {}
|
|
167
|
+
|
|
168
|
+
this.options = options
|
|
169
|
+
this.set = []
|
|
170
|
+
this.pattern = pattern
|
|
171
|
+
this.windowsPathsNoEscape = !!options.windowsPathsNoEscape ||
|
|
172
|
+
options.allowWindowsEscape === false
|
|
173
|
+
if (this.windowsPathsNoEscape) {
|
|
174
|
+
this.pattern = this.pattern.replace(/\\/g, '/')
|
|
347
175
|
}
|
|
176
|
+
this.regexp = null
|
|
177
|
+
this.negate = false
|
|
178
|
+
this.comment = false
|
|
179
|
+
this.empty = false
|
|
180
|
+
this.partial = !!options.partial
|
|
181
|
+
|
|
182
|
+
// make the set of regexps etc.
|
|
183
|
+
this.make()
|
|
348
184
|
}
|
|
349
185
|
|
|
350
|
-
|
|
351
|
-
; (i < len) && (c = pattern.charAt(i))
|
|
352
|
-
; i++) {
|
|
353
|
-
this.debug('%s\t%s %s %j', pattern, i, re, c)
|
|
186
|
+
debug () {}
|
|
354
187
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
188
|
+
make () {
|
|
189
|
+
const pattern = this.pattern
|
|
190
|
+
const options = this.options
|
|
191
|
+
|
|
192
|
+
// empty patterns and comments match nothing.
|
|
193
|
+
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
194
|
+
this.comment = true
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
if (!pattern) {
|
|
198
|
+
this.empty = true
|
|
199
|
+
return
|
|
360
200
|
}
|
|
361
201
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
case '/': {
|
|
365
|
-
// completely not allowed, even escaped.
|
|
366
|
-
// Should already be path-split by now.
|
|
367
|
-
return false
|
|
368
|
-
}
|
|
202
|
+
// step 1: figure out negation, etc.
|
|
203
|
+
this.parseNegate()
|
|
369
204
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
escaping = true
|
|
373
|
-
continue
|
|
374
|
-
|
|
375
|
-
// the various stateChar values
|
|
376
|
-
// for the "extglob" stuff.
|
|
377
|
-
case '?':
|
|
378
|
-
case '*':
|
|
379
|
-
case '+':
|
|
380
|
-
case '@':
|
|
381
|
-
case '!':
|
|
382
|
-
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
|
|
383
|
-
|
|
384
|
-
// all of those are literals inside a class, except that
|
|
385
|
-
// the glob [!a] means [^a] in regexp
|
|
386
|
-
if (inClass) {
|
|
387
|
-
this.debug(' in class')
|
|
388
|
-
if (c === '!' && i === classStart + 1) c = '^'
|
|
389
|
-
re += c
|
|
390
|
-
continue
|
|
391
|
-
}
|
|
205
|
+
// step 2: expand braces
|
|
206
|
+
let set = this.globSet = this.braceExpand()
|
|
392
207
|
|
|
393
|
-
|
|
394
|
-
// that there was something like ** or +? in there.
|
|
395
|
-
// Handle the stateChar, then proceed with this one.
|
|
396
|
-
self.debug('call clearStateChar %j', stateChar)
|
|
397
|
-
clearStateChar()
|
|
398
|
-
stateChar = c
|
|
399
|
-
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|
400
|
-
// just clear the statechar *now*, rather than even diving into
|
|
401
|
-
// the patternList stuff.
|
|
402
|
-
if (options.noext) clearStateChar()
|
|
403
|
-
continue
|
|
404
|
-
|
|
405
|
-
case '(':
|
|
406
|
-
if (inClass) {
|
|
407
|
-
re += '('
|
|
408
|
-
continue
|
|
409
|
-
}
|
|
208
|
+
if (options.debug) this.debug = (...args) => console.error(...args)
|
|
410
209
|
|
|
411
|
-
|
|
412
|
-
re += '\\('
|
|
413
|
-
continue
|
|
414
|
-
}
|
|
210
|
+
this.debug(this.pattern, set)
|
|
415
211
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
212
|
+
// step 3: now we have a set, so turn each one into a series of path-portion
|
|
213
|
+
// matching patterns.
|
|
214
|
+
// These will be regexps, except in the case of "**", which is
|
|
215
|
+
// set to the GLOBSTAR object for globstar behavior,
|
|
216
|
+
// and will not contain any / characters
|
|
217
|
+
set = this.globParts = set.map(s => s.split(slashSplit))
|
|
218
|
+
|
|
219
|
+
this.debug(this.pattern, set)
|
|
220
|
+
|
|
221
|
+
// glob --> regexps
|
|
222
|
+
set = set.map((s, si, set) => s.map(this.parse, this))
|
|
223
|
+
|
|
224
|
+
this.debug(this.pattern, set)
|
|
225
|
+
|
|
226
|
+
// filter out everything that didn't compile properly.
|
|
227
|
+
set = set.filter(s => s.indexOf(false) === -1)
|
|
228
|
+
|
|
229
|
+
this.debug(this.pattern, set)
|
|
230
|
+
|
|
231
|
+
this.set = set
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
parseNegate () {
|
|
235
|
+
if (this.options.nonegate) return
|
|
236
|
+
|
|
237
|
+
const pattern = this.pattern
|
|
238
|
+
let negate = false
|
|
239
|
+
let negateOffset = 0
|
|
240
|
+
|
|
241
|
+
for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
|
|
242
|
+
negate = !negate
|
|
243
|
+
negateOffset++
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
|
247
|
+
this.negate = negate
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// set partial to true to test if, for example,
|
|
251
|
+
// "/a/b" matches the start of "/*/b/*/d"
|
|
252
|
+
// Partial means, if you run out of file before you run
|
|
253
|
+
// out of pattern, then that's fine, as long as all
|
|
254
|
+
// the parts match.
|
|
255
|
+
matchOne (file, pattern, partial) {
|
|
256
|
+
var options = this.options
|
|
428
257
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
258
|
+
this.debug('matchOne',
|
|
259
|
+
{ 'this': this, file: file, pattern: pattern })
|
|
260
|
+
|
|
261
|
+
this.debug('matchOne', file.length, pattern.length)
|
|
262
|
+
|
|
263
|
+
for (var fi = 0,
|
|
264
|
+
pi = 0,
|
|
265
|
+
fl = file.length,
|
|
266
|
+
pl = pattern.length
|
|
267
|
+
; (fi < fl) && (pi < pl)
|
|
268
|
+
; fi++, pi++) {
|
|
269
|
+
this.debug('matchOne loop')
|
|
270
|
+
var p = pattern[pi]
|
|
271
|
+
var f = file[fi]
|
|
272
|
+
|
|
273
|
+
this.debug(pattern, p, f)
|
|
274
|
+
|
|
275
|
+
// should be impossible.
|
|
276
|
+
// some invalid regexp stuff in the set.
|
|
277
|
+
/* istanbul ignore if */
|
|
278
|
+
if (p === false) return false
|
|
279
|
+
|
|
280
|
+
if (p === GLOBSTAR) {
|
|
281
|
+
this.debug('GLOBSTAR', [pattern, p, f])
|
|
282
|
+
|
|
283
|
+
// "**"
|
|
284
|
+
// a/**/b/**/c would match the following:
|
|
285
|
+
// a/b/x/y/z/c
|
|
286
|
+
// a/x/y/z/b/c
|
|
287
|
+
// a/b/x/b/x/c
|
|
288
|
+
// a/b/c
|
|
289
|
+
// To do this, take the rest of the pattern after
|
|
290
|
+
// the **, and see if it would match the file remainder.
|
|
291
|
+
// If so, return success.
|
|
292
|
+
// If not, the ** "swallows" a segment, and try again.
|
|
293
|
+
// This is recursively awful.
|
|
294
|
+
//
|
|
295
|
+
// a/**/b/**/c matching a/b/x/y/z/c
|
|
296
|
+
// - a matches a
|
|
297
|
+
// - doublestar
|
|
298
|
+
// - matchOne(b/x/y/z/c, b/**/c)
|
|
299
|
+
// - b matches b
|
|
300
|
+
// - doublestar
|
|
301
|
+
// - matchOne(x/y/z/c, c) -> no
|
|
302
|
+
// - matchOne(y/z/c, c) -> no
|
|
303
|
+
// - matchOne(z/c, c) -> no
|
|
304
|
+
// - matchOne(c, c) yes, hit
|
|
305
|
+
var fr = fi
|
|
306
|
+
var pr = pi + 1
|
|
307
|
+
if (pr === pl) {
|
|
308
|
+
this.debug('** at the end')
|
|
309
|
+
// a ** at the end will just swallow the rest.
|
|
310
|
+
// We have found a match.
|
|
311
|
+
// however, it will not swallow /.x, unless
|
|
312
|
+
// options.dot is set.
|
|
313
|
+
// . and .. are *never* matched by **, for explosively
|
|
314
|
+
// exponential reasons.
|
|
315
|
+
for (; fi < fl; fi++) {
|
|
316
|
+
if (file[fi] === '.' || file[fi] === '..' ||
|
|
317
|
+
(!options.dot && file[fi].charAt(0) === '.')) return false
|
|
318
|
+
}
|
|
319
|
+
return true
|
|
433
320
|
}
|
|
434
321
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
322
|
+
// ok, let's see if we can swallow whatever we can.
|
|
323
|
+
while (fr < fl) {
|
|
324
|
+
var swallowee = file[fr]
|
|
325
|
+
|
|
326
|
+
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
|
|
327
|
+
|
|
328
|
+
// XXX remove this slice. Just pass the start index.
|
|
329
|
+
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
|
330
|
+
this.debug('globstar found match!', fr, fl, swallowee)
|
|
331
|
+
// found a match.
|
|
332
|
+
return true
|
|
333
|
+
} else {
|
|
334
|
+
// can't swallow "." or ".." ever.
|
|
335
|
+
// can only swallow ".foo" when explicitly asked.
|
|
336
|
+
if (swallowee === '.' || swallowee === '..' ||
|
|
337
|
+
(!options.dot && swallowee.charAt(0) === '.')) {
|
|
338
|
+
this.debug('dot detected!', file, fr, pattern, pr)
|
|
339
|
+
break
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ** swallows a segment, and continue.
|
|
343
|
+
this.debug('globstar swallow a segment, and continue')
|
|
344
|
+
fr++
|
|
345
|
+
}
|
|
443
346
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
347
|
+
|
|
348
|
+
// no match was found.
|
|
349
|
+
// However, in partial mode, we can't say this is necessarily over.
|
|
350
|
+
// If there's more *pattern* left, then
|
|
351
|
+
/* istanbul ignore if */
|
|
352
|
+
if (partial) {
|
|
353
|
+
// ran out of file
|
|
354
|
+
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
|
|
355
|
+
if (fr === fl) return true
|
|
452
356
|
}
|
|
357
|
+
return false
|
|
358
|
+
}
|
|
453
359
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
360
|
+
// something other than **
|
|
361
|
+
// non-magic patterns just have to match exactly
|
|
362
|
+
// patterns with magic have been turned into regexps.
|
|
363
|
+
var hit
|
|
364
|
+
if (typeof p === 'string') {
|
|
365
|
+
hit = f === p
|
|
366
|
+
this.debug('string match', p, f, hit)
|
|
367
|
+
} else {
|
|
368
|
+
hit = f.match(p)
|
|
369
|
+
this.debug('pattern match', p, f, hit)
|
|
370
|
+
}
|
|
457
371
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
// swallow any state-tracking char before the [
|
|
461
|
-
clearStateChar()
|
|
372
|
+
if (!hit) return false
|
|
373
|
+
}
|
|
462
374
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
375
|
+
// Note: ending in / means that we'll get a final ""
|
|
376
|
+
// at the end of the pattern. This can only match a
|
|
377
|
+
// corresponding "" at the end of the file.
|
|
378
|
+
// If the file ends in /, then it can only match a
|
|
379
|
+
// a pattern that ends in /, unless the pattern just
|
|
380
|
+
// doesn't have any more for it. But, a/b/ should *not*
|
|
381
|
+
// match "a/b/*", even though "" matches against the
|
|
382
|
+
// [^/]*? pattern, except in partial mode, where it might
|
|
383
|
+
// simply not be reached yet.
|
|
384
|
+
// However, a/b/ should still satisfy a/*
|
|
385
|
+
|
|
386
|
+
// now either we fell off the end of the pattern, or we're done.
|
|
387
|
+
if (fi === fl && pi === pl) {
|
|
388
|
+
// ran out of pattern and filename at the same time.
|
|
389
|
+
// an exact hit!
|
|
390
|
+
return true
|
|
391
|
+
} else if (fi === fl) {
|
|
392
|
+
// ran out of file, but still had pattern left.
|
|
393
|
+
// this is ok if we're doing the match as part of
|
|
394
|
+
// a glob fs traversal.
|
|
395
|
+
return partial
|
|
396
|
+
} else /* istanbul ignore else */ if (pi === pl) {
|
|
397
|
+
// ran out of pattern, still have file left.
|
|
398
|
+
// this is only acceptable if we're on the very last
|
|
399
|
+
// empty segment of a file with a trailing slash.
|
|
400
|
+
// a/* should match a/b/
|
|
401
|
+
return (fi === fl - 1) && (file[fi] === '')
|
|
402
|
+
}
|
|
467
403
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
continue
|
|
473
|
-
|
|
474
|
-
case ']':
|
|
475
|
-
// a right bracket shall lose its special
|
|
476
|
-
// meaning and represent itself in
|
|
477
|
-
// a bracket expression if it occurs
|
|
478
|
-
// first in the list. -- POSIX.2 2.8.3.2
|
|
479
|
-
if (i === classStart + 1 || !inClass) {
|
|
480
|
-
re += '\\' + c
|
|
481
|
-
escaping = false
|
|
482
|
-
continue
|
|
483
|
-
}
|
|
404
|
+
// should be unreachable.
|
|
405
|
+
/* istanbul ignore next */
|
|
406
|
+
throw new Error('wtf?')
|
|
407
|
+
}
|
|
484
408
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
409
|
+
braceExpand () {
|
|
410
|
+
return braceExpand(this.pattern, this.options)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
parse (pattern, isSub) {
|
|
414
|
+
assertValidPattern(pattern)
|
|
415
|
+
|
|
416
|
+
const options = this.options
|
|
417
|
+
|
|
418
|
+
// shortcuts
|
|
419
|
+
if (pattern === '**') {
|
|
420
|
+
if (!options.noglobstar)
|
|
421
|
+
return GLOBSTAR
|
|
422
|
+
else
|
|
423
|
+
pattern = '*'
|
|
424
|
+
}
|
|
425
|
+
if (pattern === '') return ''
|
|
426
|
+
|
|
427
|
+
let re = ''
|
|
428
|
+
let hasMagic = !!options.nocase
|
|
429
|
+
let escaping = false
|
|
430
|
+
// ? => one single character
|
|
431
|
+
const patternListStack = []
|
|
432
|
+
const negativeLists = []
|
|
433
|
+
let stateChar
|
|
434
|
+
let inClass = false
|
|
435
|
+
let reClassStart = -1
|
|
436
|
+
let classStart = -1
|
|
437
|
+
let cs
|
|
438
|
+
let pl
|
|
439
|
+
let sp
|
|
440
|
+
// . and .. never match anything that doesn't start with .,
|
|
441
|
+
// even when options.dot is set.
|
|
442
|
+
const patternStart = pattern.charAt(0) === '.' ? '' // anything
|
|
443
|
+
// not (start or / followed by . or .. followed by / or end)
|
|
444
|
+
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
|
|
445
|
+
: '(?!\\.)'
|
|
446
|
+
|
|
447
|
+
const clearStateChar = () => {
|
|
448
|
+
if (stateChar) {
|
|
449
|
+
// we had some state-tracking character
|
|
450
|
+
// that wasn't consumed by this pass.
|
|
451
|
+
switch (stateChar) {
|
|
452
|
+
case '*':
|
|
453
|
+
re += star
|
|
454
|
+
hasMagic = true
|
|
455
|
+
break
|
|
456
|
+
case '?':
|
|
457
|
+
re += qmark
|
|
458
|
+
hasMagic = true
|
|
459
|
+
break
|
|
460
|
+
default:
|
|
461
|
+
re += '\\' + stateChar
|
|
462
|
+
break
|
|
504
463
|
}
|
|
464
|
+
this.debug('clearStateChar %j %j', stateChar, re)
|
|
465
|
+
stateChar = false
|
|
466
|
+
}
|
|
467
|
+
}
|
|
505
468
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
inClass = false
|
|
509
|
-
re += c
|
|
510
|
-
continue
|
|
469
|
+
for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) {
|
|
470
|
+
this.debug('%s\t%s %s %j', pattern, i, re, c)
|
|
511
471
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
472
|
+
// skip over any that are escaped.
|
|
473
|
+
if (escaping) {
|
|
474
|
+
/* istanbul ignore next - completely not allowed, even escaped. */
|
|
475
|
+
if (c === '/') {
|
|
476
|
+
return false
|
|
477
|
+
}
|
|
515
478
|
|
|
516
|
-
if (
|
|
517
|
-
// no need
|
|
518
|
-
escaping = false
|
|
519
|
-
} else if (reSpecials[c]
|
|
520
|
-
&& !(c === '^' && inClass)) {
|
|
479
|
+
if (reSpecials[c]) {
|
|
521
480
|
re += '\\'
|
|
522
481
|
}
|
|
523
|
-
|
|
524
482
|
re += c
|
|
483
|
+
escaping = false
|
|
484
|
+
continue
|
|
485
|
+
}
|
|
525
486
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
// split where the last [ was, and escape it
|
|
533
|
-
// this is a huge pita. We now have to re-walk
|
|
534
|
-
// the contents of the would-be class to re-translate
|
|
535
|
-
// any characters that were passed through as-is
|
|
536
|
-
cs = pattern.substr(classStart + 1)
|
|
537
|
-
sp = this.parse(cs, SUBPARSE)
|
|
538
|
-
re = re.substr(0, reClassStart) + '\\[' + sp[0]
|
|
539
|
-
hasMagic = hasMagic || sp[1]
|
|
540
|
-
}
|
|
487
|
+
switch (c) {
|
|
488
|
+
/* istanbul ignore next */
|
|
489
|
+
case '/': {
|
|
490
|
+
// Should already be path-split by now.
|
|
491
|
+
return false
|
|
492
|
+
}
|
|
541
493
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
// Go through and escape them, taking care not to double-escape any
|
|
547
|
-
// | chars that were already escaped.
|
|
548
|
-
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
|
549
|
-
var tail = re.slice(pl.reStart + pl.open.length)
|
|
550
|
-
this.debug('setting tail', re, pl)
|
|
551
|
-
// maybe some even number of \, then maybe 1 \, followed by a |
|
|
552
|
-
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
|
|
553
|
-
if (!$2) {
|
|
554
|
-
// the | isn't already escaped, so escape it.
|
|
555
|
-
$2 = '\\'
|
|
556
|
-
}
|
|
494
|
+
case '\\':
|
|
495
|
+
clearStateChar()
|
|
496
|
+
escaping = true
|
|
497
|
+
continue
|
|
557
498
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
499
|
+
// the various stateChar values
|
|
500
|
+
// for the "extglob" stuff.
|
|
501
|
+
case '?':
|
|
502
|
+
case '*':
|
|
503
|
+
case '+':
|
|
504
|
+
case '@':
|
|
505
|
+
case '!':
|
|
506
|
+
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
|
|
507
|
+
|
|
508
|
+
// all of those are literals inside a class, except that
|
|
509
|
+
// the glob [!a] means [^a] in regexp
|
|
510
|
+
if (inClass) {
|
|
511
|
+
this.debug(' in class')
|
|
512
|
+
if (c === '!' && i === classStart + 1) c = '^'
|
|
513
|
+
re += c
|
|
514
|
+
continue
|
|
515
|
+
}
|
|
575
516
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
517
|
+
// if we already have a stateChar, then it means
|
|
518
|
+
// that there was something like ** or +? in there.
|
|
519
|
+
// Handle the stateChar, then proceed with this one.
|
|
520
|
+
this.debug('call clearStateChar %j', stateChar)
|
|
521
|
+
clearStateChar()
|
|
522
|
+
stateChar = c
|
|
523
|
+
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|
524
|
+
// just clear the statechar *now*, rather than even diving into
|
|
525
|
+
// the patternList stuff.
|
|
526
|
+
if (options.noext) clearStateChar()
|
|
527
|
+
continue
|
|
528
|
+
|
|
529
|
+
case '(':
|
|
530
|
+
if (inClass) {
|
|
531
|
+
re += '('
|
|
532
|
+
continue
|
|
533
|
+
}
|
|
582
534
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
case '[': case '.': case '(': addPatternStart = true
|
|
588
|
-
}
|
|
535
|
+
if (!stateChar) {
|
|
536
|
+
re += '\\('
|
|
537
|
+
continue
|
|
538
|
+
}
|
|
589
539
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
var openParensBefore = nlBefore.split('(').length - 1
|
|
609
|
-
var cleanAfter = nlAfter
|
|
610
|
-
for (i = 0; i < openParensBefore; i++) {
|
|
611
|
-
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
|
|
612
|
-
}
|
|
613
|
-
nlAfter = cleanAfter
|
|
540
|
+
patternListStack.push({
|
|
541
|
+
type: stateChar,
|
|
542
|
+
start: i - 1,
|
|
543
|
+
reStart: re.length,
|
|
544
|
+
open: plTypes[stateChar].open,
|
|
545
|
+
close: plTypes[stateChar].close
|
|
546
|
+
})
|
|
547
|
+
// negation is (?:(?!js)[^/]*)
|
|
548
|
+
re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
|
|
549
|
+
this.debug('plType %j %j', stateChar, re)
|
|
550
|
+
stateChar = false
|
|
551
|
+
continue
|
|
552
|
+
|
|
553
|
+
case ')':
|
|
554
|
+
if (inClass || !patternListStack.length) {
|
|
555
|
+
re += '\\)'
|
|
556
|
+
continue
|
|
557
|
+
}
|
|
614
558
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
559
|
+
clearStateChar()
|
|
560
|
+
hasMagic = true
|
|
561
|
+
pl = patternListStack.pop()
|
|
562
|
+
// negation is (?:(?!js)[^/]*)
|
|
563
|
+
// The others are (?:<pattern>)<type>
|
|
564
|
+
re += pl.close
|
|
565
|
+
if (pl.type === '!') {
|
|
566
|
+
negativeLists.push(pl)
|
|
567
|
+
}
|
|
568
|
+
pl.reEnd = re.length
|
|
569
|
+
continue
|
|
622
570
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
}
|
|
571
|
+
case '|':
|
|
572
|
+
if (inClass || !patternListStack.length) {
|
|
573
|
+
re += '\\|'
|
|
574
|
+
continue
|
|
575
|
+
}
|
|
629
576
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
577
|
+
clearStateChar()
|
|
578
|
+
re += '|'
|
|
579
|
+
continue
|
|
633
580
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
581
|
+
// these are mostly the same in regexp and glob
|
|
582
|
+
case '[':
|
|
583
|
+
// swallow any state-tracking char before the [
|
|
584
|
+
clearStateChar()
|
|
638
585
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
return globUnescape(pattern)
|
|
644
|
-
}
|
|
586
|
+
if (inClass) {
|
|
587
|
+
re += '\\' + c
|
|
588
|
+
continue
|
|
589
|
+
}
|
|
645
590
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
591
|
+
inClass = true
|
|
592
|
+
classStart = i
|
|
593
|
+
reClassStart = re.length
|
|
594
|
+
re += c
|
|
595
|
+
continue
|
|
596
|
+
|
|
597
|
+
case ']':
|
|
598
|
+
// a right bracket shall lose its special
|
|
599
|
+
// meaning and represent itself in
|
|
600
|
+
// a bracket expression if it occurs
|
|
601
|
+
// first in the list. -- POSIX.2 2.8.3.2
|
|
602
|
+
if (i === classStart + 1 || !inClass) {
|
|
603
|
+
re += '\\' + c
|
|
604
|
+
continue
|
|
605
|
+
}
|
|
656
606
|
|
|
657
|
-
|
|
658
|
-
|
|
607
|
+
// handle the case where we left a class open.
|
|
608
|
+
// "[z-a]" is valid, equivalent to "\[z-a\]"
|
|
609
|
+
// split where the last [ was, make sure we don't have
|
|
610
|
+
// an invalid re. if so, re-walk the contents of the
|
|
611
|
+
// would-be class to re-translate any characters that
|
|
612
|
+
// were passed through as-is
|
|
613
|
+
// TODO: It would probably be faster to determine this
|
|
614
|
+
// without a try/catch and a new RegExp, but it's tricky
|
|
615
|
+
// to do safely. For now, this is safe and works.
|
|
616
|
+
cs = pattern.substring(classStart + 1, i)
|
|
617
|
+
try {
|
|
618
|
+
RegExp('[' + cs + ']')
|
|
619
|
+
} catch (er) {
|
|
620
|
+
// not a valid class!
|
|
621
|
+
sp = this.parse(cs, SUBPARSE)
|
|
622
|
+
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
|
|
623
|
+
hasMagic = hasMagic || sp[1]
|
|
624
|
+
inClass = false
|
|
625
|
+
continue
|
|
626
|
+
}
|
|
659
627
|
|
|
660
|
-
|
|
661
|
-
|
|
628
|
+
// finish up the class.
|
|
629
|
+
hasMagic = true
|
|
630
|
+
inClass = false
|
|
631
|
+
re += c
|
|
632
|
+
continue
|
|
662
633
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
634
|
+
default:
|
|
635
|
+
// swallow any state char that wasn't consumed
|
|
636
|
+
clearStateChar()
|
|
666
637
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
638
|
+
if (reSpecials[c] && !(c === '^' && inClass)) {
|
|
639
|
+
re += '\\'
|
|
640
|
+
}
|
|
670
641
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
642
|
+
re += c
|
|
643
|
+
break
|
|
644
|
+
|
|
645
|
+
} // switch
|
|
646
|
+
} // for
|
|
647
|
+
|
|
648
|
+
// handle the case where we left a class open.
|
|
649
|
+
// "[abc" is valid, equivalent to "\[abc"
|
|
650
|
+
if (inClass) {
|
|
651
|
+
// split where the last [ was, and escape it
|
|
652
|
+
// this is a huge pita. We now have to re-walk
|
|
653
|
+
// the contents of the would-be class to re-translate
|
|
654
|
+
// any characters that were passed through as-is
|
|
655
|
+
cs = pattern.substr(classStart + 1)
|
|
656
|
+
sp = this.parse(cs, SUBPARSE)
|
|
657
|
+
re = re.substr(0, reClassStart) + '\\[' + sp[0]
|
|
658
|
+
hasMagic = hasMagic || sp[1]
|
|
659
|
+
}
|
|
678
660
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
}).join('|')
|
|
697
|
-
|
|
698
|
-
// must match entire pattern
|
|
699
|
-
// ending in a * or ** will make it less strict.
|
|
700
|
-
re = '^(?:' + re + ')$'
|
|
701
|
-
|
|
702
|
-
// can match anything, as long as it's not this.
|
|
703
|
-
if (this.negate) re = '^(?!' + re + ').*$'
|
|
704
|
-
|
|
705
|
-
try {
|
|
706
|
-
this.regexp = new RegExp(re, flags)
|
|
707
|
-
} catch (ex) /* istanbul ignore next - should be impossible */ {
|
|
708
|
-
this.regexp = false
|
|
709
|
-
}
|
|
710
|
-
return this.regexp
|
|
711
|
-
}
|
|
661
|
+
// handle the case where we had a +( thing at the *end*
|
|
662
|
+
// of the pattern.
|
|
663
|
+
// each pattern list stack adds 3 chars, and we need to go through
|
|
664
|
+
// and escape any | chars that were passed through as-is for the regexp.
|
|
665
|
+
// Go through and escape them, taking care not to double-escape any
|
|
666
|
+
// | chars that were already escaped.
|
|
667
|
+
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
|
668
|
+
let tail
|
|
669
|
+
tail = re.slice(pl.reStart + pl.open.length)
|
|
670
|
+
this.debug('setting tail', re, pl)
|
|
671
|
+
// maybe some even number of \, then maybe 1 \, followed by a |
|
|
672
|
+
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
|
|
673
|
+
/* istanbul ignore else - should already be done */
|
|
674
|
+
if (!$2) {
|
|
675
|
+
// the | isn't already escaped, so escape it.
|
|
676
|
+
$2 = '\\'
|
|
677
|
+
}
|
|
712
678
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
679
|
+
// need to escape all those slashes *again*, without escaping the
|
|
680
|
+
// one that we need for escaping the | character. As it works out,
|
|
681
|
+
// escaping an even number of slashes can be done by simply repeating
|
|
682
|
+
// it exactly after itself. That's why this trick works.
|
|
683
|
+
//
|
|
684
|
+
// I am sorry that you have to see this.
|
|
685
|
+
return $1 + $1 + $2 + '|'
|
|
686
|
+
})
|
|
687
|
+
|
|
688
|
+
this.debug('tail=%j\n %s', tail, tail, pl, re)
|
|
689
|
+
const t = pl.type === '*' ? star
|
|
690
|
+
: pl.type === '?' ? qmark
|
|
691
|
+
: '\\' + pl.type
|
|
692
|
+
|
|
693
|
+
hasMagic = true
|
|
694
|
+
re = re.slice(0, pl.reStart) + t + '\\(' + tail
|
|
695
|
+
}
|
|
724
696
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
if (this.empty) return f === ''
|
|
697
|
+
// handle trailing things that only matter at the very end.
|
|
698
|
+
clearStateChar()
|
|
699
|
+
if (escaping) {
|
|
700
|
+
// trailing \\
|
|
701
|
+
re += '\\\\'
|
|
702
|
+
}
|
|
732
703
|
|
|
733
|
-
|
|
704
|
+
// only need to apply the nodot start if the re starts with
|
|
705
|
+
// something that could conceivably capture a dot
|
|
706
|
+
const addPatternStart = addPatternStartSet[re.charAt(0)]
|
|
707
|
+
|
|
708
|
+
// Hack to work around lack of negative lookbehind in JS
|
|
709
|
+
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
|
710
|
+
// like 'a.xyz.yz' doesn't match. So, the first negative
|
|
711
|
+
// lookahead, has to look ALL the way ahead, to the end of
|
|
712
|
+
// the pattern.
|
|
713
|
+
for (let n = negativeLists.length - 1; n > -1; n--) {
|
|
714
|
+
const nl = negativeLists[n]
|
|
715
|
+
|
|
716
|
+
const nlBefore = re.slice(0, nl.reStart)
|
|
717
|
+
const nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
|
|
718
|
+
let nlAfter = re.slice(nl.reEnd)
|
|
719
|
+
const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter
|
|
720
|
+
|
|
721
|
+
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
|
722
|
+
// mean that we should *not* include the ) in the bit that is considered
|
|
723
|
+
// "after" the negated section.
|
|
724
|
+
const openParensBefore = nlBefore.split('(').length - 1
|
|
725
|
+
let cleanAfter = nlAfter
|
|
726
|
+
for (let i = 0; i < openParensBefore; i++) {
|
|
727
|
+
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
|
|
728
|
+
}
|
|
729
|
+
nlAfter = cleanAfter
|
|
734
730
|
|
|
735
|
-
|
|
731
|
+
const dollar = nlAfter === '' && isSub !== SUBPARSE ? '$' : ''
|
|
732
|
+
re = nlBefore + nlFirst + nlAfter + dollar + nlLast
|
|
733
|
+
}
|
|
736
734
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
735
|
+
// if the re is not "" at this point, then we need to make sure
|
|
736
|
+
// it doesn't match against an empty path part.
|
|
737
|
+
// Otherwise a/* will match a/, which it should not.
|
|
738
|
+
if (re !== '' && hasMagic) {
|
|
739
|
+
re = '(?=.)' + re
|
|
740
|
+
}
|
|
741
741
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
742
|
+
if (addPatternStart) {
|
|
743
|
+
re = patternStart + re
|
|
744
|
+
}
|
|
745
745
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
746
|
+
// parsing just a piece of a larger pattern.
|
|
747
|
+
if (isSub === SUBPARSE) {
|
|
748
|
+
return [re, hasMagic]
|
|
749
|
+
}
|
|
750
750
|
|
|
751
|
-
|
|
752
|
-
|
|
751
|
+
// skip the regexp for non-magical patterns
|
|
752
|
+
// unescape anything in it, though, so that it'll be
|
|
753
|
+
// an exact match against a file etc.
|
|
754
|
+
if (!hasMagic) {
|
|
755
|
+
return globUnescape(pattern)
|
|
756
|
+
}
|
|
753
757
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
758
|
+
const flags = options.nocase ? 'i' : ''
|
|
759
|
+
try {
|
|
760
|
+
return Object.assign(new RegExp('^' + re + '$', flags), {
|
|
761
|
+
_glob: pattern,
|
|
762
|
+
_src: re,
|
|
763
|
+
})
|
|
764
|
+
} catch (er) /* istanbul ignore next - should be impossible */ {
|
|
765
|
+
// If it was an invalid regular expression, then it can't match
|
|
766
|
+
// anything. This trick looks for a character after the end of
|
|
767
|
+
// the string, which is of course impossible, except in multi-line
|
|
768
|
+
// mode, but it's not a /m regex.
|
|
769
|
+
return new RegExp('$.')
|
|
770
|
+
}
|
|
760
771
|
}
|
|
761
772
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
773
|
+
makeRe () {
|
|
774
|
+
if (this.regexp || this.regexp === false) return this.regexp
|
|
775
|
+
|
|
776
|
+
// at this point, this.set is a 2d array of partial
|
|
777
|
+
// pattern strings, or "**".
|
|
778
|
+
//
|
|
779
|
+
// It's better to use .match(). This function shouldn't
|
|
780
|
+
// be used, really, but it's pretty convenient sometimes,
|
|
781
|
+
// when you just want to work with a regex.
|
|
782
|
+
const set = this.set
|
|
783
|
+
|
|
784
|
+
if (!set.length) {
|
|
785
|
+
this.regexp = false
|
|
786
|
+
return this.regexp
|
|
767
787
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
788
|
+
const options = this.options
|
|
789
|
+
|
|
790
|
+
const twoStar = options.noglobstar ? star
|
|
791
|
+
: options.dot ? twoStarDot
|
|
792
|
+
: twoStarNoDot
|
|
793
|
+
const flags = options.nocase ? 'i' : ''
|
|
794
|
+
|
|
795
|
+
// coalesce globstars and regexpify non-globstar patterns
|
|
796
|
+
// if it's the only item, then we just do one twoStar
|
|
797
|
+
// if it's the first, and there are more, prepend (\/|twoStar\/)? to next
|
|
798
|
+
// if it's the last, append (\/twoStar|) to previous
|
|
799
|
+
// if it's in the middle, append (\/|\/twoStar\/) to previous
|
|
800
|
+
// then filter out GLOBSTAR symbols
|
|
801
|
+
let re = set.map(pattern => {
|
|
802
|
+
pattern = pattern.map(p =>
|
|
803
|
+
typeof p === 'string' ? regExpEscape(p)
|
|
804
|
+
: p === GLOBSTAR ? GLOBSTAR
|
|
805
|
+
: p._src
|
|
806
|
+
).reduce((set, p) => {
|
|
807
|
+
if (!(set[set.length - 1] === GLOBSTAR && p === GLOBSTAR)) {
|
|
808
|
+
set.push(p)
|
|
809
|
+
}
|
|
810
|
+
return set
|
|
811
|
+
}, [])
|
|
812
|
+
pattern.forEach((p, i) => {
|
|
813
|
+
if (p !== GLOBSTAR || pattern[i-1] === GLOBSTAR) {
|
|
814
|
+
return
|
|
815
|
+
}
|
|
816
|
+
if (i === 0) {
|
|
817
|
+
if (pattern.length > 1) {
|
|
818
|
+
pattern[i+1] = '(?:\\\/|' + twoStar + '\\\/)?' + pattern[i+1]
|
|
819
|
+
} else {
|
|
820
|
+
pattern[i] = twoStar
|
|
821
|
+
}
|
|
822
|
+
} else if (i === pattern.length - 1) {
|
|
823
|
+
pattern[i-1] += '(?:\\\/|' + twoStar + ')?'
|
|
824
|
+
} else {
|
|
825
|
+
pattern[i-1] += '(?:\\\/|\\\/' + twoStar + '\\\/)' + pattern[i+1]
|
|
826
|
+
pattern[i+1] = GLOBSTAR
|
|
827
|
+
}
|
|
828
|
+
})
|
|
829
|
+
return pattern.filter(p => p !== GLOBSTAR).join('/')
|
|
830
|
+
}).join('|')
|
|
831
|
+
|
|
832
|
+
// must match entire pattern
|
|
833
|
+
// ending in a * or ** will make it less strict.
|
|
834
|
+
re = '^(?:' + re + ')$'
|
|
835
|
+
|
|
836
|
+
// can match anything, as long as it's not this.
|
|
837
|
+
if (this.negate) re = '^(?!' + re + ').*$'
|
|
838
|
+
|
|
839
|
+
try {
|
|
840
|
+
this.regexp = new RegExp(re, flags)
|
|
841
|
+
} catch (ex) /* istanbul ignore next - should be impossible */ {
|
|
842
|
+
this.regexp = false
|
|
772
843
|
}
|
|
844
|
+
return this.regexp
|
|
773
845
|
}
|
|
774
846
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
847
|
+
match (f, partial = this.partial) {
|
|
848
|
+
this.debug('match', f, this.pattern)
|
|
849
|
+
// short-circuit in the case of busted things.
|
|
850
|
+
// comments, etc.
|
|
851
|
+
if (this.comment) return false
|
|
852
|
+
if (this.empty) return f === ''
|
|
780
853
|
|
|
781
|
-
|
|
782
|
-
// "/a/b" matches the start of "/*/b/*/d"
|
|
783
|
-
// Partial means, if you run out of file before you run
|
|
784
|
-
// out of pattern, then that's fine, as long as all
|
|
785
|
-
// the parts match.
|
|
786
|
-
Minimatch.prototype.matchOne = function (file, pattern, partial) {
|
|
787
|
-
var options = this.options
|
|
788
|
-
|
|
789
|
-
this.debug('matchOne',
|
|
790
|
-
{ 'this': this, file: file, pattern: pattern })
|
|
791
|
-
|
|
792
|
-
this.debug('matchOne', file.length, pattern.length)
|
|
793
|
-
|
|
794
|
-
for (var fi = 0,
|
|
795
|
-
pi = 0,
|
|
796
|
-
fl = file.length,
|
|
797
|
-
pl = pattern.length
|
|
798
|
-
; (fi < fl) && (pi < pl)
|
|
799
|
-
; fi++, pi++) {
|
|
800
|
-
this.debug('matchOne loop')
|
|
801
|
-
var p = pattern[pi]
|
|
802
|
-
var f = file[fi]
|
|
803
|
-
|
|
804
|
-
this.debug(pattern, p, f)
|
|
805
|
-
|
|
806
|
-
// should be impossible.
|
|
807
|
-
// some invalid regexp stuff in the set.
|
|
808
|
-
/* istanbul ignore if */
|
|
809
|
-
if (p === false) return false
|
|
810
|
-
|
|
811
|
-
if (p === GLOBSTAR) {
|
|
812
|
-
this.debug('GLOBSTAR', [pattern, p, f])
|
|
813
|
-
|
|
814
|
-
// "**"
|
|
815
|
-
// a/**/b/**/c would match the following:
|
|
816
|
-
// a/b/x/y/z/c
|
|
817
|
-
// a/x/y/z/b/c
|
|
818
|
-
// a/b/x/b/x/c
|
|
819
|
-
// a/b/c
|
|
820
|
-
// To do this, take the rest of the pattern after
|
|
821
|
-
// the **, and see if it would match the file remainder.
|
|
822
|
-
// If so, return success.
|
|
823
|
-
// If not, the ** "swallows" a segment, and try again.
|
|
824
|
-
// This is recursively awful.
|
|
825
|
-
//
|
|
826
|
-
// a/**/b/**/c matching a/b/x/y/z/c
|
|
827
|
-
// - a matches a
|
|
828
|
-
// - doublestar
|
|
829
|
-
// - matchOne(b/x/y/z/c, b/**/c)
|
|
830
|
-
// - b matches b
|
|
831
|
-
// - doublestar
|
|
832
|
-
// - matchOne(x/y/z/c, c) -> no
|
|
833
|
-
// - matchOne(y/z/c, c) -> no
|
|
834
|
-
// - matchOne(z/c, c) -> no
|
|
835
|
-
// - matchOne(c, c) yes, hit
|
|
836
|
-
var fr = fi
|
|
837
|
-
var pr = pi + 1
|
|
838
|
-
if (pr === pl) {
|
|
839
|
-
this.debug('** at the end')
|
|
840
|
-
// a ** at the end will just swallow the rest.
|
|
841
|
-
// We have found a match.
|
|
842
|
-
// however, it will not swallow /.x, unless
|
|
843
|
-
// options.dot is set.
|
|
844
|
-
// . and .. are *never* matched by **, for explosively
|
|
845
|
-
// exponential reasons.
|
|
846
|
-
for (; fi < fl; fi++) {
|
|
847
|
-
if (file[fi] === '.' || file[fi] === '..' ||
|
|
848
|
-
(!options.dot && file[fi].charAt(0) === '.')) return false
|
|
849
|
-
}
|
|
850
|
-
return true
|
|
851
|
-
}
|
|
854
|
+
if (f === '/' && partial) return true
|
|
852
855
|
|
|
853
|
-
|
|
854
|
-
while (fr < fl) {
|
|
855
|
-
var swallowee = file[fr]
|
|
856
|
+
const options = this.options
|
|
856
857
|
|
|
857
|
-
|
|
858
|
+
// windows: need to use /, not \
|
|
859
|
+
if (path.sep !== '/') {
|
|
860
|
+
f = f.split(path.sep).join('/')
|
|
861
|
+
}
|
|
858
862
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
// found a match.
|
|
863
|
-
return true
|
|
864
|
-
} else {
|
|
865
|
-
// can't swallow "." or ".." ever.
|
|
866
|
-
// can only swallow ".foo" when explicitly asked.
|
|
867
|
-
if (swallowee === '.' || swallowee === '..' ||
|
|
868
|
-
(!options.dot && swallowee.charAt(0) === '.')) {
|
|
869
|
-
this.debug('dot detected!', file, fr, pattern, pr)
|
|
870
|
-
break
|
|
871
|
-
}
|
|
863
|
+
// treat the test path as a set of pathparts.
|
|
864
|
+
f = f.split(slashSplit)
|
|
865
|
+
this.debug(this.pattern, 'split', f)
|
|
872
866
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
}
|
|
867
|
+
// just ONE of the pattern sets in this.set needs to match
|
|
868
|
+
// in order for it to be valid. If negating, then just one
|
|
869
|
+
// match means that we have failed.
|
|
870
|
+
// Either way, return on the first hit.
|
|
878
871
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
}
|
|
888
|
-
return false
|
|
872
|
+
const set = this.set
|
|
873
|
+
this.debug(this.pattern, 'set', set)
|
|
874
|
+
|
|
875
|
+
// Find the basename of the path by looking for the last non-empty segment
|
|
876
|
+
let filename
|
|
877
|
+
for (let i = f.length - 1; i >= 0; i--) {
|
|
878
|
+
filename = f[i]
|
|
879
|
+
if (filename) break
|
|
889
880
|
}
|
|
890
881
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
this.
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
882
|
+
for (let i = 0; i < set.length; i++) {
|
|
883
|
+
const pattern = set[i]
|
|
884
|
+
let file = f
|
|
885
|
+
if (options.matchBase && pattern.length === 1) {
|
|
886
|
+
file = [filename]
|
|
887
|
+
}
|
|
888
|
+
const hit = this.matchOne(file, pattern, partial)
|
|
889
|
+
if (hit) {
|
|
890
|
+
if (options.flipNegate) return true
|
|
891
|
+
return !this.negate
|
|
892
|
+
}
|
|
901
893
|
}
|
|
902
894
|
|
|
903
|
-
if
|
|
895
|
+
// didn't get any hits. this is success if it's a negative
|
|
896
|
+
// pattern, failure otherwise.
|
|
897
|
+
if (options.flipNegate) return false
|
|
898
|
+
return this.negate
|
|
904
899
|
}
|
|
905
900
|
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
// corresponding "" at the end of the file.
|
|
909
|
-
// If the file ends in /, then it can only match a
|
|
910
|
-
// a pattern that ends in /, unless the pattern just
|
|
911
|
-
// doesn't have any more for it. But, a/b/ should *not*
|
|
912
|
-
// match "a/b/*", even though "" matches against the
|
|
913
|
-
// [^/]*? pattern, except in partial mode, where it might
|
|
914
|
-
// simply not be reached yet.
|
|
915
|
-
// However, a/b/ should still satisfy a/*
|
|
916
|
-
|
|
917
|
-
// now either we fell off the end of the pattern, or we're done.
|
|
918
|
-
if (fi === fl && pi === pl) {
|
|
919
|
-
// ran out of pattern and filename at the same time.
|
|
920
|
-
// an exact hit!
|
|
921
|
-
return true
|
|
922
|
-
} else if (fi === fl) {
|
|
923
|
-
// ran out of file, but still had pattern left.
|
|
924
|
-
// this is ok if we're doing the match as part of
|
|
925
|
-
// a glob fs traversal.
|
|
926
|
-
return partial
|
|
927
|
-
} else /* istanbul ignore else */ if (pi === pl) {
|
|
928
|
-
// ran out of pattern, still have file left.
|
|
929
|
-
// this is only acceptable if we're on the very last
|
|
930
|
-
// empty segment of a file with a trailing slash.
|
|
931
|
-
// a/* should match a/b/
|
|
932
|
-
return (fi === fl - 1) && (file[fi] === '')
|
|
901
|
+
static defaults (def) {
|
|
902
|
+
return minimatch.defaults(def).Minimatch
|
|
933
903
|
}
|
|
934
|
-
|
|
935
|
-
// should be unreachable.
|
|
936
|
-
/* istanbul ignore next */
|
|
937
|
-
throw new Error('wtf?')
|
|
938
904
|
}
|
|
939
905
|
|
|
940
|
-
|
|
941
|
-
function globUnescape (s) {
|
|
942
|
-
return s.replace(/\\(.)/g, '$1')
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
function regExpEscape (s) {
|
|
946
|
-
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
|
947
|
-
}
|
|
906
|
+
minimatch.Minimatch = Minimatch
|