summaryrefslogtreecommitdiff
path: root/node_modules/glob/dist/cjs/src/walker.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/glob/dist/cjs/src/walker.js')
-rw-r--r--node_modules/glob/dist/cjs/src/walker.js358
1 files changed, 358 insertions, 0 deletions
diff --git a/node_modules/glob/dist/cjs/src/walker.js b/node_modules/glob/dist/cjs/src/walker.js
new file mode 100644
index 0000000..9651ce1
--- /dev/null
+++ b/node_modules/glob/dist/cjs/src/walker.js
@@ -0,0 +1,358 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.GlobStream = exports.GlobWalker = exports.GlobUtil = void 0;
+/**
+ * Single-use utility classes to provide functionality to the {@link Glob}
+ * methods.
+ *
+ * @module
+ */
+const minipass_1 = require("minipass");
+const ignore_js_1 = require("./ignore.js");
+const processor_js_1 = require("./processor.js");
+const makeIgnore = (ignore, opts) => typeof ignore === 'string'
+ ? new ignore_js_1.Ignore([ignore], opts)
+ : Array.isArray(ignore)
+ ? new ignore_js_1.Ignore(ignore, opts)
+ : ignore;
+/**
+ * basic walking utilities that all the glob walker types use
+ */
+class GlobUtil {
+ path;
+ patterns;
+ opts;
+ seen = new Set();
+ paused = false;
+ aborted = false;
+ #onResume = [];
+ #ignore;
+ #sep;
+ signal;
+ maxDepth;
+ constructor(patterns, path, opts) {
+ this.patterns = patterns;
+ this.path = path;
+ this.opts = opts;
+ this.#sep = !opts.posix && opts.platform === 'win32' ? '\\' : '/';
+ if (opts.ignore) {
+ this.#ignore = makeIgnore(opts.ignore, opts);
+ }
+ // ignore, always set with maxDepth, but it's optional on the
+ // GlobOptions type
+ /* c8 ignore start */
+ this.maxDepth = opts.maxDepth || Infinity;
+ /* c8 ignore stop */
+ if (opts.signal) {
+ this.signal = opts.signal;
+ this.signal.addEventListener('abort', () => {
+ this.#onResume.length = 0;
+ });
+ }
+ }
+ #ignored(path) {
+ return this.seen.has(path) || !!this.#ignore?.ignored?.(path);
+ }
+ #childrenIgnored(path) {
+ return !!this.#ignore?.childrenIgnored?.(path);
+ }
+ // backpressure mechanism
+ pause() {
+ this.paused = true;
+ }
+ resume() {
+ /* c8 ignore start */
+ if (this.signal?.aborted)
+ return;
+ /* c8 ignore stop */
+ this.paused = false;
+ let fn = undefined;
+ while (!this.paused && (fn = this.#onResume.shift())) {
+ fn();
+ }
+ }
+ onResume(fn) {
+ if (this.signal?.aborted)
+ return;
+ /* c8 ignore start */
+ if (!this.paused) {
+ fn();
+ }
+ else {
+ /* c8 ignore stop */
+ this.#onResume.push(fn);
+ }
+ }
+ // do the requisite realpath/stat checking, and return the path
+ // to add or undefined to filter it out.
+ async matchCheck(e, ifDir) {
+ if (ifDir && this.opts.nodir)
+ return undefined;
+ let rpc;
+ if (this.opts.realpath) {
+ rpc = e.realpathCached() || (await e.realpath());
+ if (!rpc)
+ return undefined;
+ e = rpc;
+ }
+ const needStat = e.isUnknown() || this.opts.stat;
+ return this.matchCheckTest(needStat ? await e.lstat() : e, ifDir);
+ }
+ matchCheckTest(e, ifDir) {
+ return e &&
+ (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&
+ (!ifDir || e.canReaddir()) &&
+ (!this.opts.nodir || !e.isDirectory()) &&
+ !this.#ignored(e)
+ ? e
+ : undefined;
+ }
+ matchCheckSync(e, ifDir) {
+ if (ifDir && this.opts.nodir)
+ return undefined;
+ let rpc;
+ if (this.opts.realpath) {
+ rpc = e.realpathCached() || e.realpathSync();
+ if (!rpc)
+ return undefined;
+ e = rpc;
+ }
+ const needStat = e.isUnknown() || this.opts.stat;
+ return this.matchCheckTest(needStat ? e.lstatSync() : e, ifDir);
+ }
+ matchFinish(e, absolute) {
+ if (this.#ignored(e))
+ return;
+ const abs = this.opts.absolute === undefined ? absolute : this.opts.absolute;
+ this.seen.add(e);
+ const mark = this.opts.mark && e.isDirectory() ? this.#sep : '';
+ // ok, we have what we need!
+ if (this.opts.withFileTypes) {
+ this.matchEmit(e);
+ }
+ else if (abs) {
+ const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath();
+ this.matchEmit(abs + mark);
+ }
+ else {
+ const rel = this.opts.posix ? e.relativePosix() : e.relative();
+ const pre = this.opts.dotRelative && !rel.startsWith('..' + this.#sep)
+ ? '.' + this.#sep
+ : '';
+ this.matchEmit(!rel ? '.' + mark : pre + rel + mark);
+ }
+ }
+ async match(e, absolute, ifDir) {
+ const p = await this.matchCheck(e, ifDir);
+ if (p)
+ this.matchFinish(p, absolute);
+ }
+ matchSync(e, absolute, ifDir) {
+ const p = this.matchCheckSync(e, ifDir);
+ if (p)
+ this.matchFinish(p, absolute);
+ }
+ walkCB(target, patterns, cb) {
+ /* c8 ignore start */
+ if (this.signal?.aborted)
+ cb();
+ /* c8 ignore stop */
+ this.walkCB2(target, patterns, new processor_js_1.Processor(this.opts), cb);
+ }
+ walkCB2(target, patterns, processor, cb) {
+ if (this.#childrenIgnored(target))
+ return cb();
+ if (this.signal?.aborted)
+ cb();
+ if (this.paused) {
+ this.onResume(() => this.walkCB2(target, patterns, processor, cb));
+ return;
+ }
+ processor.processPatterns(target, patterns);
+ // done processing. all of the above is sync, can be abstracted out.
+ // subwalks is a map of paths to the entry filters they need
+ // matches is a map of paths to [absolute, ifDir] tuples.
+ let tasks = 1;
+ const next = () => {
+ if (--tasks === 0)
+ cb();
+ };
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
+ if (this.#ignored(m))
+ continue;
+ tasks++;
+ this.match(m, absolute, ifDir).then(() => next());
+ }
+ for (const t of processor.subwalkTargets()) {
+ if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
+ continue;
+ }
+ tasks++;
+ const childrenCached = t.readdirCached();
+ if (t.calledReaddir())
+ this.walkCB3(t, childrenCached, processor, next);
+ else {
+ t.readdirCB((_, entries) => this.walkCB3(t, entries, processor, next), true);
+ }
+ }
+ next();
+ }
+ walkCB3(target, entries, processor, cb) {
+ processor = processor.filterEntries(target, entries);
+ let tasks = 1;
+ const next = () => {
+ if (--tasks === 0)
+ cb();
+ };
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
+ if (this.#ignored(m))
+ continue;
+ tasks++;
+ this.match(m, absolute, ifDir).then(() => next());
+ }
+ for (const [target, patterns] of processor.subwalks.entries()) {
+ tasks++;
+ this.walkCB2(target, patterns, processor.child(), next);
+ }
+ next();
+ }
+ walkCBSync(target, patterns, cb) {
+ /* c8 ignore start */
+ if (this.signal?.aborted)
+ cb();
+ /* c8 ignore stop */
+ this.walkCB2Sync(target, patterns, new processor_js_1.Processor(this.opts), cb);
+ }
+ walkCB2Sync(target, patterns, processor, cb) {
+ if (this.#childrenIgnored(target))
+ return cb();
+ if (this.signal?.aborted)
+ cb();
+ if (this.paused) {
+ this.onResume(() => this.walkCB2Sync(target, patterns, processor, cb));
+ return;
+ }
+ processor.processPatterns(target, patterns);
+ // done processing. all of the above is sync, can be abstracted out.
+ // subwalks is a map of paths to the entry filters they need
+ // matches is a map of paths to [absolute, ifDir] tuples.
+ let tasks = 1;
+ const next = () => {
+ if (--tasks === 0)
+ cb();
+ };
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
+ if (this.#ignored(m))
+ continue;
+ this.matchSync(m, absolute, ifDir);
+ }
+ for (const t of processor.subwalkTargets()) {
+ if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
+ continue;
+ }
+ tasks++;
+ const children = t.readdirSync();
+ this.walkCB3Sync(t, children, processor, next);
+ }
+ next();
+ }
+ walkCB3Sync(target, entries, processor, cb) {
+ processor = processor.filterEntries(target, entries);
+ let tasks = 1;
+ const next = () => {
+ if (--tasks === 0)
+ cb();
+ };
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
+ if (this.#ignored(m))
+ continue;
+ this.matchSync(m, absolute, ifDir);
+ }
+ for (const [target, patterns] of processor.subwalks.entries()) {
+ tasks++;
+ this.walkCB2Sync(target, patterns, processor.child(), next);
+ }
+ next();
+ }
+}
+exports.GlobUtil = GlobUtil;
+class GlobWalker extends GlobUtil {
+ matches;
+ constructor(patterns, path, opts) {
+ super(patterns, path, opts);
+ this.matches = new Set();
+ }
+ matchEmit(e) {
+ this.matches.add(e);
+ }
+ async walk() {
+ if (this.signal?.aborted)
+ throw this.signal.reason;
+ if (this.path.isUnknown()) {
+ await this.path.lstat();
+ }
+ await new Promise((res, rej) => {
+ this.walkCB(this.path, this.patterns, () => {
+ if (this.signal?.aborted) {
+ rej(this.signal.reason);
+ }
+ else {
+ res(this.matches);
+ }
+ });
+ });
+ return this.matches;
+ }
+ walkSync() {
+ if (this.signal?.aborted)
+ throw this.signal.reason;
+ if (this.path.isUnknown()) {
+ this.path.lstatSync();
+ }
+ // nothing for the callback to do, because this never pauses
+ this.walkCBSync(this.path, this.patterns, () => {
+ if (this.signal?.aborted)
+ throw this.signal.reason;
+ });
+ return this.matches;
+ }
+}
+exports.GlobWalker = GlobWalker;
+class GlobStream extends GlobUtil {
+ results;
+ constructor(patterns, path, opts) {
+ super(patterns, path, opts);
+ this.results = new minipass_1.Minipass({
+ signal: this.signal,
+ objectMode: true,
+ });
+ this.results.on('drain', () => this.resume());
+ this.results.on('resume', () => this.resume());
+ }
+ matchEmit(e) {
+ this.results.write(e);
+ if (!this.results.flowing)
+ this.pause();
+ }
+ stream() {
+ const target = this.path;
+ if (target.isUnknown()) {
+ target.lstat().then(() => {
+ this.walkCB(target, this.patterns, () => this.results.end());
+ });
+ }
+ else {
+ this.walkCB(target, this.patterns, () => this.results.end());
+ }
+ return this.results;
+ }
+ streamSync() {
+ if (this.path.isUnknown()) {
+ this.path.lstatSync();
+ }
+ this.walkCBSync(this.path, this.patterns, () => this.results.end());
+ return this.results;
+ }
+}
+exports.GlobStream = GlobStream;
+//# sourceMappingURL=walker.js.map \ No newline at end of file