1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
const fs = require('fs')
const globrex = require('globrex')
const { promisify } = require('util')
const globalyzer = require('globalyzer')
const { join, resolve, relative } = require('path')
const isHidden = /(^|[\\\/])\.[^\\\/\.]/g
const readdir = promisify(fs.readdir)
const stat = promisify(fs.stat)
let CACHE = {}
async function walk(output, prefix, lexer, opts, dirname = '', level = 0) {
if (output.length === 1) return
const rgx = lexer.segments[level]
const dir = join(opts.cwd, prefix, dirname)
const files = await readdir(dir)
const { dot, filesOnly } = opts
let i = 0,
len = files.length,
file
let fullpath, relpath, stats, isMatch
for (; i < len; i++) {
file = files[i]
if (file === 'node_modules') continue
fullpath = join(dir, file)
relpath = dirname ? join(dirname, file) : file
if (!dot && isHidden.test(relpath)) continue
isMatch = lexer.regex.test(relpath)
if ((stats = CACHE[relpath]) === void 0) {
CACHE[relpath] = stats = fs.lstatSync(fullpath)
}
if (!stats.isDirectory()) {
if (isMatch) {
output.push(relative(opts.cwd, fullpath))
return
}
continue
}
if (rgx && !rgx.test(file)) continue
if (!filesOnly && isMatch) {
output.push(join(prefix, relpath))
return
}
await walk(
output,
prefix,
lexer,
opts,
relpath,
rgx && rgx.toString() !== lexer.globstar && ++level
)
}
}
/**
* Find files using bash-like globbing.
* All paths are normalized compared to node-glob.
* @param {String} str Glob string
* @param {String} [options.cwd='.'] Current working directory
* @param {Boolean} [options.dot=false] Include dotfile matches
* @param {Boolean} [options.absolute=false] Return absolute paths
* @param {Boolean} [options.filesOnly=false] Do not include folders if true
* @param {Boolean} [options.flush=false] Reset cache object
* @returns {Array} array containing matching files
*/
export async function globSingle(str, opts = {}) {
if (!str) return []
let glob = globalyzer(str)
opts.cwd = opts.cwd || '.'
if (!glob.isGlob) {
try {
let resolved = resolve(opts.cwd, str)
let dirent = await stat(resolved)
if (opts.filesOnly && !dirent.isFile()) return []
return opts.absolute ? [resolved] : [str]
} catch (err) {
if (err.code != 'ENOENT') throw err
return []
}
}
if (opts.flush) CACHE = {}
let matches = []
const { path } = globrex(glob.glob, {
filepath: true,
globstar: true,
extended: true,
})
path.globstar = path.globstar.toString()
await walk(matches, glob.base, path, opts, '.', 0)
return opts.absolute ? matches.map((x) => resolve(opts.cwd, x)) : matches
}
|