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