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