1 | const fs = require('fs');
|
2 | const globrex = require('globrex');
|
3 | const globalyzer = require('globalyzer');
|
4 | const { join, resolve, relative } = require('path');
|
5 | const { promisify } = require('util');
|
6 | const isHidden = /(^|\/)\.[^\/\.]/g;
|
7 | const readdir = promisify(fs.readdir);
|
8 |
|
9 | let CACHE = {};
|
10 |
|
11 | async function walk(output, prefix, lexer, opts, dirname='', level=0) {
|
12 | const rgx = lexer.segments[level];
|
13 | const dir = join(opts.cwd, prefix, dirname);
|
14 | const files = await readdir(dir);
|
15 | const { dot, filesOnly } = opts;
|
16 |
|
17 | let i=0, len=files.length, file;
|
18 | let fullpath, relpath, stats, isMatch;
|
19 |
|
20 | for (; i < len; i++) {
|
21 | fullpath = join(dir, file=files[i]);
|
22 | relpath = dirname ? join(dirname, file) : file;
|
23 | if (!dot && isHidden.test(relpath)) continue;
|
24 | isMatch = lexer.regex.test(relpath);
|
25 |
|
26 | if ((stats=CACHE[relpath]) === void 0) {
|
27 | CACHE[relpath] = stats = fs.lstatSync(fullpath);
|
28 | }
|
29 |
|
30 | if (!stats.isDirectory()) {
|
31 | isMatch && output.push(relative(opts.cwd, fullpath));
|
32 | continue;
|
33 | }
|
34 |
|
35 | if (rgx && !rgx.test(file)) continue;
|
36 | !filesOnly && isMatch && output.push(join(prefix, relpath));
|
37 |
|
38 | await walk(output, prefix, lexer, opts, relpath, rgx && rgx.toString() !== lexer.globster && ++level);
|
39 | }
|
40 | }
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | module.exports = async function (str, opts={}) {
|
54 | let glob = globalyzer(str);
|
55 |
|
56 | if (!glob.isGlob) return fs.existsSync(str) ? [str] : [];
|
57 | if (opts.flush) CACHE = {};
|
58 |
|
59 | let matches = [];
|
60 | opts.cwd = opts.cwd || '.';
|
61 | const { path } = globrex(glob.glob, { filepath:true, globstar:true, extended:true });
|
62 |
|
63 | await walk(matches, glob.base, path, opts, '.', 0);
|
64 |
|
65 | return opts.absolute ? matches.map(x => resolve(opts.cwd, x)) : matches;
|
66 | };
|