source: trip-planner-front/node_modules/glob/sync.js@ 6fe77af

Last change on this file since 6fe77af was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 11.7 KB
Line 
1module.exports = globSync
2globSync.GlobSync = GlobSync
3
4var fs = require('fs')
5var rp = require('fs.realpath')
6var minimatch = require('minimatch')
7var Minimatch = minimatch.Minimatch
8var Glob = require('./glob.js').Glob
9var util = require('util')
10var path = require('path')
11var assert = require('assert')
12var isAbsolute = require('path-is-absolute')
13var common = require('./common.js')
14var setopts = common.setopts
15var ownProp = common.ownProp
16var childrenIgnored = common.childrenIgnored
17var isIgnored = common.isIgnored
18
19function globSync (pattern, options) {
20 if (typeof options === 'function' || arguments.length === 3)
21 throw new TypeError('callback provided to sync glob\n'+
22 'See: https://github.com/isaacs/node-glob/issues/167')
23
24 return new GlobSync(pattern, options).found
25}
26
27function GlobSync (pattern, options) {
28 if (!pattern)
29 throw new Error('must provide pattern')
30
31 if (typeof options === 'function' || arguments.length === 3)
32 throw new TypeError('callback provided to sync glob\n'+
33 'See: https://github.com/isaacs/node-glob/issues/167')
34
35 if (!(this instanceof GlobSync))
36 return new GlobSync(pattern, options)
37
38 setopts(this, pattern, options)
39
40 if (this.noprocess)
41 return this
42
43 var n = this.minimatch.set.length
44 this.matches = new Array(n)
45 for (var i = 0; i < n; i ++) {
46 this._process(this.minimatch.set[i], i, false)
47 }
48 this._finish()
49}
50
51GlobSync.prototype._finish = function () {
52 assert(this instanceof GlobSync)
53 if (this.realpath) {
54 var self = this
55 this.matches.forEach(function (matchset, index) {
56 var set = self.matches[index] = Object.create(null)
57 for (var p in matchset) {
58 try {
59 p = self._makeAbs(p)
60 var real = rp.realpathSync(p, self.realpathCache)
61 set[real] = true
62 } catch (er) {
63 if (er.syscall === 'stat')
64 set[self._makeAbs(p)] = true
65 else
66 throw er
67 }
68 }
69 })
70 }
71 common.finish(this)
72}
73
74
75GlobSync.prototype._process = function (pattern, index, inGlobStar) {
76 assert(this instanceof GlobSync)
77
78 // Get the first [n] parts of pattern that are all strings.
79 var n = 0
80 while (typeof pattern[n] === 'string') {
81 n ++
82 }
83 // now n is the index of the first one that is *not* a string.
84
85 // See if there's anything else
86 var prefix
87 switch (n) {
88 // if not, then this is rather simple
89 case pattern.length:
90 this._processSimple(pattern.join('/'), index)
91 return
92
93 case 0:
94 // pattern *starts* with some non-trivial item.
95 // going to readdir(cwd), but not include the prefix in matches.
96 prefix = null
97 break
98
99 default:
100 // pattern has some string bits in the front.
101 // whatever it starts with, whether that's 'absolute' like /foo/bar,
102 // or 'relative' like '../baz'
103 prefix = pattern.slice(0, n).join('/')
104 break
105 }
106
107 var remain = pattern.slice(n)
108
109 // get the list of entries.
110 var read
111 if (prefix === null)
112 read = '.'
113 else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
114 if (!prefix || !isAbsolute(prefix))
115 prefix = '/' + prefix
116 read = prefix
117 } else
118 read = prefix
119
120 var abs = this._makeAbs(read)
121
122 //if ignored, skip processing
123 if (childrenIgnored(this, read))
124 return
125
126 var isGlobStar = remain[0] === minimatch.GLOBSTAR
127 if (isGlobStar)
128 this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
129 else
130 this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
131}
132
133
134GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
135 var entries = this._readdir(abs, inGlobStar)
136
137 // if the abs isn't a dir, then nothing can match!
138 if (!entries)
139 return
140
141 // It will only match dot entries if it starts with a dot, or if
142 // dot is set. Stuff like @(.foo|.bar) isn't allowed.
143 var pn = remain[0]
144 var negate = !!this.minimatch.negate
145 var rawGlob = pn._glob
146 var dotOk = this.dot || rawGlob.charAt(0) === '.'
147
148 var matchedEntries = []
149 for (var i = 0; i < entries.length; i++) {
150 var e = entries[i]
151 if (e.charAt(0) !== '.' || dotOk) {
152 var m
153 if (negate && !prefix) {
154 m = !e.match(pn)
155 } else {
156 m = e.match(pn)
157 }
158 if (m)
159 matchedEntries.push(e)
160 }
161 }
162
163 var len = matchedEntries.length
164 // If there are no matched entries, then nothing matches.
165 if (len === 0)
166 return
167
168 // if this is the last remaining pattern bit, then no need for
169 // an additional stat *unless* the user has specified mark or
170 // stat explicitly. We know they exist, since readdir returned
171 // them.
172
173 if (remain.length === 1 && !this.mark && !this.stat) {
174 if (!this.matches[index])
175 this.matches[index] = Object.create(null)
176
177 for (var i = 0; i < len; i ++) {
178 var e = matchedEntries[i]
179 if (prefix) {
180 if (prefix.slice(-1) !== '/')
181 e = prefix + '/' + e
182 else
183 e = prefix + e
184 }
185
186 if (e.charAt(0) === '/' && !this.nomount) {
187 e = path.join(this.root, e)
188 }
189 this._emitMatch(index, e)
190 }
191 // This was the last one, and no stats were needed
192 return
193 }
194
195 // now test all matched entries as stand-ins for that part
196 // of the pattern.
197 remain.shift()
198 for (var i = 0; i < len; i ++) {
199 var e = matchedEntries[i]
200 var newPattern
201 if (prefix)
202 newPattern = [prefix, e]
203 else
204 newPattern = [e]
205 this._process(newPattern.concat(remain), index, inGlobStar)
206 }
207}
208
209
210GlobSync.prototype._emitMatch = function (index, e) {
211 if (isIgnored(this, e))
212 return
213
214 var abs = this._makeAbs(e)
215
216 if (this.mark)
217 e = this._mark(e)
218
219 if (this.absolute) {
220 e = abs
221 }
222
223 if (this.matches[index][e])
224 return
225
226 if (this.nodir) {
227 var c = this.cache[abs]
228 if (c === 'DIR' || Array.isArray(c))
229 return
230 }
231
232 this.matches[index][e] = true
233
234 if (this.stat)
235 this._stat(e)
236}
237
238
239GlobSync.prototype._readdirInGlobStar = function (abs) {
240 // follow all symlinked directories forever
241 // just proceed as if this is a non-globstar situation
242 if (this.follow)
243 return this._readdir(abs, false)
244
245 var entries
246 var lstat
247 var stat
248 try {
249 lstat = fs.lstatSync(abs)
250 } catch (er) {
251 if (er.code === 'ENOENT') {
252 // lstat failed, doesn't exist
253 return null
254 }
255 }
256
257 var isSym = lstat && lstat.isSymbolicLink()
258 this.symlinks[abs] = isSym
259
260 // If it's not a symlink or a dir, then it's definitely a regular file.
261 // don't bother doing a readdir in that case.
262 if (!isSym && lstat && !lstat.isDirectory())
263 this.cache[abs] = 'FILE'
264 else
265 entries = this._readdir(abs, false)
266
267 return entries
268}
269
270GlobSync.prototype._readdir = function (abs, inGlobStar) {
271 var entries
272
273 if (inGlobStar && !ownProp(this.symlinks, abs))
274 return this._readdirInGlobStar(abs)
275
276 if (ownProp(this.cache, abs)) {
277 var c = this.cache[abs]
278 if (!c || c === 'FILE')
279 return null
280
281 if (Array.isArray(c))
282 return c
283 }
284
285 try {
286 return this._readdirEntries(abs, fs.readdirSync(abs))
287 } catch (er) {
288 this._readdirError(abs, er)
289 return null
290 }
291}
292
293GlobSync.prototype._readdirEntries = function (abs, entries) {
294 // if we haven't asked to stat everything, then just
295 // assume that everything in there exists, so we can avoid
296 // having to stat it a second time.
297 if (!this.mark && !this.stat) {
298 for (var i = 0; i < entries.length; i ++) {
299 var e = entries[i]
300 if (abs === '/')
301 e = abs + e
302 else
303 e = abs + '/' + e
304 this.cache[e] = true
305 }
306 }
307
308 this.cache[abs] = entries
309
310 // mark and cache dir-ness
311 return entries
312}
313
314GlobSync.prototype._readdirError = function (f, er) {
315 // handle errors, and cache the information
316 switch (er.code) {
317 case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
318 case 'ENOTDIR': // totally normal. means it *does* exist.
319 var abs = this._makeAbs(f)
320 this.cache[abs] = 'FILE'
321 if (abs === this.cwdAbs) {
322 var error = new Error(er.code + ' invalid cwd ' + this.cwd)
323 error.path = this.cwd
324 error.code = er.code
325 throw error
326 }
327 break
328
329 case 'ENOENT': // not terribly unusual
330 case 'ELOOP':
331 case 'ENAMETOOLONG':
332 case 'UNKNOWN':
333 this.cache[this._makeAbs(f)] = false
334 break
335
336 default: // some unusual error. Treat as failure.
337 this.cache[this._makeAbs(f)] = false
338 if (this.strict)
339 throw er
340 if (!this.silent)
341 console.error('glob error', er)
342 break
343 }
344}
345
346GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
347
348 var entries = this._readdir(abs, inGlobStar)
349
350 // no entries means not a dir, so it can never have matches
351 // foo.txt/** doesn't match foo.txt
352 if (!entries)
353 return
354
355 // test without the globstar, and with every child both below
356 // and replacing the globstar.
357 var remainWithoutGlobStar = remain.slice(1)
358 var gspref = prefix ? [ prefix ] : []
359 var noGlobStar = gspref.concat(remainWithoutGlobStar)
360
361 // the noGlobStar pattern exits the inGlobStar state
362 this._process(noGlobStar, index, false)
363
364 var len = entries.length
365 var isSym = this.symlinks[abs]
366
367 // If it's a symlink, and we're in a globstar, then stop
368 if (isSym && inGlobStar)
369 return
370
371 for (var i = 0; i < len; i++) {
372 var e = entries[i]
373 if (e.charAt(0) === '.' && !this.dot)
374 continue
375
376 // these two cases enter the inGlobStar state
377 var instead = gspref.concat(entries[i], remainWithoutGlobStar)
378 this._process(instead, index, true)
379
380 var below = gspref.concat(entries[i], remain)
381 this._process(below, index, true)
382 }
383}
384
385GlobSync.prototype._processSimple = function (prefix, index) {
386 // XXX review this. Shouldn't it be doing the mounting etc
387 // before doing stat? kinda weird?
388 var exists = this._stat(prefix)
389
390 if (!this.matches[index])
391 this.matches[index] = Object.create(null)
392
393 // If it doesn't exist, then just mark the lack of results
394 if (!exists)
395 return
396
397 if (prefix && isAbsolute(prefix) && !this.nomount) {
398 var trail = /[\/\\]$/.test(prefix)
399 if (prefix.charAt(0) === '/') {
400 prefix = path.join(this.root, prefix)
401 } else {
402 prefix = path.resolve(this.root, prefix)
403 if (trail)
404 prefix += '/'
405 }
406 }
407
408 if (process.platform === 'win32')
409 prefix = prefix.replace(/\\/g, '/')
410
411 // Mark this as a match
412 this._emitMatch(index, prefix)
413}
414
415// Returns either 'DIR', 'FILE', or false
416GlobSync.prototype._stat = function (f) {
417 var abs = this._makeAbs(f)
418 var needDir = f.slice(-1) === '/'
419
420 if (f.length > this.maxLength)
421 return false
422
423 if (!this.stat && ownProp(this.cache, abs)) {
424 var c = this.cache[abs]
425
426 if (Array.isArray(c))
427 c = 'DIR'
428
429 // It exists, but maybe not how we need it
430 if (!needDir || c === 'DIR')
431 return c
432
433 if (needDir && c === 'FILE')
434 return false
435
436 // otherwise we have to stat, because maybe c=true
437 // if we know it exists, but not what it is.
438 }
439
440 var exists
441 var stat = this.statCache[abs]
442 if (!stat) {
443 var lstat
444 try {
445 lstat = fs.lstatSync(abs)
446 } catch (er) {
447 if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
448 this.statCache[abs] = false
449 return false
450 }
451 }
452
453 if (lstat && lstat.isSymbolicLink()) {
454 try {
455 stat = fs.statSync(abs)
456 } catch (er) {
457 stat = lstat
458 }
459 } else {
460 stat = lstat
461 }
462 }
463
464 this.statCache[abs] = stat
465
466 var c = true
467 if (stat)
468 c = stat.isDirectory() ? 'DIR' : 'FILE'
469
470 this.cache[abs] = this.cache[abs] || c
471
472 if (needDir && c === 'FILE')
473 return false
474
475 return c
476}
477
478GlobSync.prototype._mark = function (p) {
479 return common.mark(this, p)
480}
481
482GlobSync.prototype._makeAbs = function (f) {
483 return common.makeAbs(this, f)
484}
Note: See TracBrowser for help on using the repository browser.