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