243 lines
8.0 KiB
JavaScript
243 lines
8.0 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Glob = void 0;
|
|
const minimatch_1 = require("minimatch");
|
|
const path_scurry_1 = require("path-scurry");
|
|
const url_1 = require("url");
|
|
const pattern_js_1 = require("./pattern.js");
|
|
const walker_js_1 = require("./walker.js");
|
|
// if no process global, just call it linux.
|
|
// so we default to case-sensitive, / separators
|
|
const defaultPlatform = typeof process === 'object' &&
|
|
process &&
|
|
typeof process.platform === 'string'
|
|
? process.platform
|
|
: 'linux';
|
|
/**
|
|
* An object that can perform glob pattern traversals.
|
|
*/
|
|
class Glob {
|
|
absolute;
|
|
cwd;
|
|
root;
|
|
dot;
|
|
dotRelative;
|
|
follow;
|
|
ignore;
|
|
magicalBraces;
|
|
mark;
|
|
matchBase;
|
|
maxDepth;
|
|
nobrace;
|
|
nocase;
|
|
nodir;
|
|
noext;
|
|
noglobstar;
|
|
pattern;
|
|
platform;
|
|
realpath;
|
|
scurry;
|
|
stat;
|
|
signal;
|
|
windowsPathsNoEscape;
|
|
withFileTypes;
|
|
/**
|
|
* The options provided to the constructor.
|
|
*/
|
|
opts;
|
|
/**
|
|
* An array of parsed immutable {@link Pattern} objects.
|
|
*/
|
|
patterns;
|
|
/**
|
|
* All options are stored as properties on the `Glob` object.
|
|
*
|
|
* See {@link GlobOptions} for full options descriptions.
|
|
*
|
|
* Note that a previous `Glob` object can be passed as the
|
|
* `GlobOptions` to another `Glob` instantiation to re-use settings
|
|
* and caches with a new pattern.
|
|
*
|
|
* Traversal functions can be called multiple times to run the walk
|
|
* again.
|
|
*/
|
|
constructor(pattern, opts) {
|
|
/* c8 ignore start */
|
|
if (!opts)
|
|
throw new TypeError('glob options required');
|
|
/* c8 ignore stop */
|
|
this.withFileTypes = !!opts.withFileTypes;
|
|
this.signal = opts.signal;
|
|
this.follow = !!opts.follow;
|
|
this.dot = !!opts.dot;
|
|
this.dotRelative = !!opts.dotRelative;
|
|
this.nodir = !!opts.nodir;
|
|
this.mark = !!opts.mark;
|
|
if (!opts.cwd) {
|
|
this.cwd = '';
|
|
}
|
|
else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {
|
|
opts.cwd = (0, url_1.fileURLToPath)(opts.cwd);
|
|
}
|
|
this.cwd = opts.cwd || '';
|
|
this.root = opts.root;
|
|
this.magicalBraces = !!opts.magicalBraces;
|
|
this.nobrace = !!opts.nobrace;
|
|
this.noext = !!opts.noext;
|
|
this.realpath = !!opts.realpath;
|
|
this.absolute = opts.absolute;
|
|
this.noglobstar = !!opts.noglobstar;
|
|
this.matchBase = !!opts.matchBase;
|
|
this.maxDepth =
|
|
typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity;
|
|
this.stat = !!opts.stat;
|
|
this.ignore = opts.ignore;
|
|
if (this.withFileTypes && this.absolute !== undefined) {
|
|
throw new Error('cannot set absolute and withFileTypes:true');
|
|
}
|
|
if (typeof pattern === 'string') {
|
|
pattern = [pattern];
|
|
}
|
|
this.windowsPathsNoEscape =
|
|
!!opts.windowsPathsNoEscape ||
|
|
opts.allowWindowsEscape === false;
|
|
if (this.windowsPathsNoEscape) {
|
|
pattern = pattern.map(p => p.replace(/\\/g, '/'));
|
|
}
|
|
if (this.matchBase) {
|
|
if (opts.noglobstar) {
|
|
throw new TypeError('base matching requires globstar');
|
|
}
|
|
pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`));
|
|
}
|
|
this.pattern = pattern;
|
|
this.platform = opts.platform || defaultPlatform;
|
|
this.opts = { ...opts, platform: this.platform };
|
|
if (opts.scurry) {
|
|
this.scurry = opts.scurry;
|
|
if (opts.nocase !== undefined &&
|
|
opts.nocase !== opts.scurry.nocase) {
|
|
throw new Error('nocase option contradicts provided scurry option');
|
|
}
|
|
}
|
|
else {
|
|
const Scurry = opts.platform === 'win32'
|
|
? path_scurry_1.PathScurryWin32
|
|
: opts.platform === 'darwin'
|
|
? path_scurry_1.PathScurryDarwin
|
|
: opts.platform
|
|
? path_scurry_1.PathScurryPosix
|
|
: path_scurry_1.PathScurry;
|
|
this.scurry = new Scurry(this.cwd, {
|
|
nocase: opts.nocase,
|
|
fs: opts.fs,
|
|
});
|
|
}
|
|
this.nocase = this.scurry.nocase;
|
|
// If you do nocase:true on a case-sensitive file system, then
|
|
// we need to use regexps instead of strings for non-magic
|
|
// path portions, because statting `aBc` won't return results
|
|
// for the file `AbC` for example.
|
|
const nocaseMagicOnly = this.platform === 'darwin' || this.platform === 'win32';
|
|
const mmo = {
|
|
// default nocase based on platform
|
|
...opts,
|
|
dot: this.dot,
|
|
matchBase: this.matchBase,
|
|
nobrace: this.nobrace,
|
|
nocase: this.nocase,
|
|
nocaseMagicOnly,
|
|
nocomment: true,
|
|
noext: this.noext,
|
|
nonegate: true,
|
|
optimizationLevel: 2,
|
|
platform: this.platform,
|
|
windowsPathsNoEscape: this.windowsPathsNoEscape,
|
|
debug: !!this.opts.debug,
|
|
};
|
|
const mms = this.pattern.map(p => new minimatch_1.Minimatch(p, mmo));
|
|
const [matchSet, globParts] = mms.reduce((set, m) => {
|
|
set[0].push(...m.set);
|
|
set[1].push(...m.globParts);
|
|
return set;
|
|
}, [[], []]);
|
|
this.patterns = matchSet.map((set, i) => {
|
|
const g = globParts[i];
|
|
/* c8 ignore start */
|
|
if (!g)
|
|
throw new Error('invalid pattern object');
|
|
/* c8 ignore stop */
|
|
return new pattern_js_1.Pattern(set, g, 0, this.platform);
|
|
});
|
|
}
|
|
async walk() {
|
|
// Walkers always return array of Path objects, so we just have to
|
|
// coerce them into the right shape. It will have already called
|
|
// realpath() if the option was set to do so, so we know that's cached.
|
|
// start out knowing the cwd, at least
|
|
return [
|
|
...(await new walker_js_1.GlobWalker(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity
|
|
? this.maxDepth + this.scurry.cwd.depth()
|
|
: Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
}).walk()),
|
|
];
|
|
}
|
|
walkSync() {
|
|
return [
|
|
...new walker_js_1.GlobWalker(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity
|
|
? this.maxDepth + this.scurry.cwd.depth()
|
|
: Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
}).walkSync(),
|
|
];
|
|
}
|
|
stream() {
|
|
return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity
|
|
? this.maxDepth + this.scurry.cwd.depth()
|
|
: Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
}).stream();
|
|
}
|
|
streamSync() {
|
|
return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity
|
|
? this.maxDepth + this.scurry.cwd.depth()
|
|
: Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
}).streamSync();
|
|
}
|
|
/**
|
|
* Default sync iteration function. Returns a Generator that
|
|
* iterates over the results.
|
|
*/
|
|
iterateSync() {
|
|
return this.streamSync()[Symbol.iterator]();
|
|
}
|
|
[Symbol.iterator]() {
|
|
return this.iterateSync();
|
|
}
|
|
/**
|
|
* Default async iteration function. Returns an AsyncGenerator that
|
|
* iterates over the results.
|
|
*/
|
|
iterate() {
|
|
return this.stream()[Symbol.asyncIterator]();
|
|
}
|
|
[Symbol.asyncIterator]() {
|
|
return this.iterate();
|
|
}
|
|
}
|
|
exports.Glob = Glob;
|
|
//# sourceMappingURL=glob.js.map
|