File Explorer

/var/runtime/node_modules/@aws-sdk/node_modules/glob/dist/esm

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

walker.js12.3 KB · 381 lines
/** * Single-use utility classes to provide functionality to the {@link Glob} * methods. * * @module */import { Minipass } from 'minipass';import { Ignore } from './ignore.js';import { Processor } from './processor.js';const makeIgnore = (ignore, opts) => typeof ignore === 'string' ? new Ignore([ignore], opts)    : Array.isArray(ignore) ? new Ignore(ignore, opts)        : ignore;/** * basic walking utilities that all the glob walker types use */export class GlobUtil {    path;    patterns;    opts;    seen = new Set();    paused = false;    aborted = false;    #onResume = [];    #ignore;    #sep;    signal;    maxDepth;    includeChildMatches;    constructor(patterns, path, opts) {        this.patterns = patterns;        this.path = path;        this.opts = opts;        this.#sep = !opts.posix && opts.platform === 'win32' ? '\\' : '/';        this.includeChildMatches = opts.includeChildMatches !== false;        if (opts.ignore || !this.includeChildMatches) {            this.#ignore = makeIgnore(opts.ignore ?? [], opts);            if (!this.includeChildMatches &&                typeof this.#ignore.add !== 'function') {                const m = 'cannot ignore child matches, ignore lacks add() method.';                throw new Error(m);            }        }        // 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;        const s = needStat ? await e.lstat() : e;        if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {            const target = await s.realpath();            /* c8 ignore start */            if (target && (target.isUnknown() || this.opts.stat)) {                await target.lstat();            }            /* c8 ignore stop */        }        return this.matchCheckTest(s, ifDir);    }    matchCheckTest(e, ifDir) {        return (e &&            (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&            (!ifDir || e.canReaddir()) &&            (!this.opts.nodir || !e.isDirectory()) &&            (!this.opts.nodir ||                !this.opts.follow ||                !e.isSymbolicLink() ||                !e.realpathCached()?.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;        const s = needStat ? e.lstatSync() : e;        if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {            const target = s.realpathSync();            if (target && (target?.isUnknown() || this.opts.stat)) {                target.lstatSync();            }        }        return this.matchCheckTest(s, ifDir);    }    matchFinish(e, absolute) {        if (this.#ignored(e))            return;        // we know we have an ignore if this is false, but TS doesn't        if (!this.includeChildMatches && this.#ignore?.add) {            const ign = `${e.relativePosix()}/**`;            this.#ignore.add(ign);        }        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(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(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();    }}export class GlobWalker extends GlobUtil {    matches = new Set();    constructor(patterns, path, opts) {        super(patterns, path, opts);    }    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;    }}export class GlobStream extends GlobUtil {    results;    constructor(patterns, path, opts) {        super(patterns, path, opts);        this.results = new 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;    }}//# sourceMappingURL=walker.js.map