Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50654 views
1
// This is a JavaScript implementation of the fnmatch-like
2
// stuff that git uses in its .gitignore files.
3
// See `man 5 gitignore`.
4
5
module.exports = minimatch
6
7
var path = require("path")
8
, LRU = require("lru-cache")
9
10
minimatch.filter = function (pattern, options) {
11
options = options || {}
12
return function (p, i, list) {
13
return minimatch(p, pattern, options)
14
}
15
}
16
17
minimatch.match = function (list, pattern, options) {
18
if (!options) options = {}
19
var ret = list.filter(minimatch.filter(pattern, options))
20
if (options.debug) console.error("\nmatch: %s %j %j", pattern, list, ret)
21
22
// set the null flag to allow empty match sets
23
// Note that minimatch itself, and filter(), do not
24
// respect this flag, only minimatch.match(list, pattern) does.
25
if (!options.null && !ret.length) {
26
return [pattern]
27
}
28
29
return ret
30
}
31
32
function minimatch (p, pattern, options) {
33
if (typeof pattern !== "string") {
34
throw new TypeError("glob pattern string required")
35
}
36
37
options = options || {}
38
39
// to set the cache, just replace with a different obj
40
// supporting set(k,v) and v=get(k) methods.
41
var cache = options.cache || minimatch.cache
42
if (!cache) cache = minimatch.cache = new LRU(1000)
43
44
// "" only matches ""
45
if (!pattern) return p === ""
46
47
// comments.
48
if (pattern.trim().charAt(0) === "#") return false
49
50
// check the cache
51
var re = cache.get(pattern + "\n" + JSON.stringify(options))
52
if (!re && re !== false) {
53
cache.set(pattern, re = minimatch.makeRe(pattern, options))
54
}
55
56
if (options.debug) {
57
console.error(pattern + "\t" + re, JSON.stringify(p))
58
}
59
60
// some kind of invalid thing
61
if (!re) return false
62
63
64
// patterns that end in / can only match dirs
65
// however, dirs also match the same thing that *doesn't*
66
// end in a slash.
67
var match =
68
// a/ should not match a/*, but will match */
69
// accomplish this by not applying the regexp
70
// directly, unless the pattern would match
71
// trailing slash'ed things, or the thing isn't
72
// a trailing slash, or slashes are opted-in
73
( ( options.slash ||
74
p.substr(-1) !== "/" ||
75
pattern.substr(-1) === "/" )
76
&& !!p.match(re) )
77
78
// a/ should match * or a
79
|| ( p.substr(-1) === "/" &&
80
!!p.slice(0, -1).match(re) )
81
82
// a pattern with *no* slashes will match against
83
// either the full path, or just the basename.
84
|| ( options.matchBase &&
85
pattern.indexOf("/") === -1 &&
86
path.basename(p).match(re) )
87
88
//console.error(" MINIMATCH: %j %j %j %j",
89
// re.toString(), pattern, p, match)
90
return match
91
}
92
93
minimatch.makeRe = makeRe
94
function makeRe (pattern, options) {
95
options = options || {}
96
97
function clearStateChar () {
98
if (stateChar) {
99
// we had some state-tracking character
100
// that wasn't consumed by this pass.
101
switch (stateChar) {
102
case "*":
103
re += oneStar
104
break
105
case "?":
106
re += "."
107
break
108
default:
109
re += "\\"+stateChar
110
break
111
}
112
stateChar = false
113
}
114
}
115
116
var braceDepth = 0
117
, re = ""
118
, escaping = false
119
, oneStar = options.dot ? "[^\\/]*?"
120
: "(?:(?!(?:\\\/|^)\\.)[^\\/])*?"
121
, twoStar = options.dot ? ".*?"
122
// not a ^ or / followed by a dot,
123
// followed by anything, any number of times.
124
: "(?:(?!(?:\\\/|^)\\.).)*?"
125
, reSpecials = "().*{}+?[]^$/\\"
126
, patternListStack = []
127
, stateChar
128
, negate = false
129
, negating = false
130
, inClass = false
131
, reClassStart = -1
132
, classStart = -1
133
, classStartPattern = options.dot ? ""
134
: "(?:(?!(?:\\\/|^)\\.)"
135
, classEndPattern = options.dot ? "" : ")"
136
137
for ( var i = 0, len = pattern.length, c
138
; (i < len) && (c = pattern.charAt(i))
139
; i ++ ) {
140
141
if (options.debug) {
142
console.error("%s\t%s %s %j", pattern, i, re, c)
143
}
144
145
switch (c) {
146
case "\\":
147
if (stateChar) {
148
if (stateChar === "*") re += oneStar
149
else re += "\\" + stateChar
150
stateChar = false
151
}
152
if (escaping) {
153
re += "\\\\" // must match literal \
154
escaping = false
155
} else {
156
escaping = true
157
}
158
continue
159
160
// the various stateChar values
161
case "!":
162
if (i === 0 || negating) {
163
negate = !negate
164
negating = true
165
break
166
} else {
167
negating = false
168
}
169
// fallthrough
170
case "+":
171
case "@":
172
case "*":
173
case "?":
174
if (options.debug) {
175
console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c)
176
}
177
178
negating = false
179
if (escaping) {
180
re += "\\" + c
181
escaping = false
182
} else if (inClass) {
183
re += c
184
} else if (c === "*" && stateChar === "*") { // **
185
re += twoStar
186
stateChar = false
187
} else {
188
if (stateChar) {
189
if (stateChar === "*") re += oneStar
190
else if (stateChar === "?") re += "."
191
else re += "\\" + stateChar
192
}
193
stateChar = c
194
}
195
continue
196
197
case "(":
198
if (escaping) {
199
re += "\\("
200
escaping = false
201
} else if (inClass) {
202
re += "("
203
} else if (stateChar) {
204
plType = stateChar
205
patternListStack.push(plType)
206
re += stateChar === "!" ? "(?!" : "(?:"
207
stateChar = false
208
} else {
209
re += "\\("
210
}
211
continue
212
213
case ")":
214
if (escaping || inClass) {
215
re += "\\)"
216
escaping = false
217
} else if (patternListStack.length) {
218
re += ")"
219
plType = patternListStack.pop()
220
switch (plType) {
221
case "?":
222
case "+":
223
case "*": re += plType
224
case "!":
225
case "@": break
226
}
227
} else {
228
re += "\\)"
229
}
230
continue
231
232
case "|":
233
if (escaping || inClass) {
234
re += "\\|"
235
escaping = false
236
} else if (patternListStack.length) {
237
re += "|"
238
} else {
239
re += "\\|"
240
}
241
continue
242
243
// these are mostly the same in regexp and glob :)
244
case "[":
245
// swallow any state-tracking char before the [
246
clearStateChar()
247
248
if (escaping || inClass) {
249
re += "\\" + c
250
escaping = false
251
} else {
252
inClass = true
253
classStart = i
254
reClassStart = re.length
255
re += classStartPattern
256
re += c
257
}
258
continue
259
260
case "]":
261
// a right bracket shall lose its special
262
// meaning and represent itself in
263
// a bracket expression if it occurs
264
// first in the list. -- POSIX.2 2.8.3.2
265
if (i === classStart + 1) escaping = true
266
267
if (escaping || !inClass) {
268
re += "\\" + c
269
escaping = false
270
} else {
271
inClass = false
272
re += c + classEndPattern
273
}
274
continue
275
276
case "{":
277
if (escaping || inClass) {
278
re += "\\{"
279
escaping = false
280
} else {
281
re += "(?:"
282
braceDepth ++
283
}
284
continue
285
286
case "}":
287
if (escaping || inClass || braceDepth === 0) {
288
re += "\\}"
289
escaping = false
290
} else {
291
// swallow any state char that wasn't consumed
292
clearStateChar()
293
re += ")"
294
braceDepth --
295
}
296
continue
297
298
case ",":
299
if (escaping || inClass || braceDepth === 0) {
300
re += ","
301
escaping = false
302
} else {
303
// swallow any state char that wasn't consumed
304
clearStateChar()
305
re += "|"
306
}
307
continue
308
309
default:
310
// swallow any state char that wasn't consumed
311
clearStateChar()
312
313
if (escaping) {
314
// no need
315
escaping = false
316
} else if (reSpecials.indexOf(c) !== -1
317
&& !(c === "^" && inClass)) {
318
re += "\\"
319
}
320
321
re += c
322
323
} // switch
324
325
if (negating && c !== "!") negating = false
326
327
} // for
328
329
// handle trailing things that only matter at the very end.
330
if (stateChar) {
331
clearStateChar()
332
} else if (escaping) {
333
re += "\\\\"
334
}
335
336
// "[abc" is valid, equivalent to "\[abc"
337
if (inClass) {
338
// split where the last [ was, and escape it
339
// this is a huge pita. We now have to re-walk
340
// the contents of the would-be class to re-translate
341
// any characters that were passed through as-is
342
var cs = re.substr(reClassStart + classStartPattern.length + 1)
343
, csOpts = Object.create(options)
344
csOpts.partial = true
345
346
re = re.substr(0, reClassStart) + "\\["
347
+ makeRe(cs, csOpts)
348
}
349
350
if (options.partial) return re
351
352
// must match entire pattern
353
// ending in a * or ** will make it less strict.
354
re = "^" + re + "$"
355
356
// fail on the pattern, but allow anything otherwise.
357
if (negate) re = "^(?!" + re + ").*$"
358
359
// really insane glob patterns can cause bad things.
360
var flags = ""
361
if (options.nocase) flags += "i"
362
363
if (options.debug) {
364
console.error("/%s/%s", re, flags)
365
}
366
367
try {
368
return new RegExp(re, flags)
369
} catch(ex) {
370
return false
371
}
372
}
373
374