Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
walker.js387 linesDownload Raw Back to commonjs
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.GlobStream = exports.GlobWalker = exports.GlobUtil = void 0;
4/**
5 * Single-use utility classes to provide functionality to the {@link Glob}
6 * methods.
7 *
8 * @module
9 */
10const minipass_1 = require("minipass");
11const ignore_js_1 = require("./ignore.js");
12const processor_js_1 = require("./processor.js");
13const makeIgnore = (ignore, opts) => typeof ignore === 'string' ? new ignore_js_1.Ignore([ignore], opts)
14    : Array.isArray(ignore) ? new ignore_js_1.Ignore(ignore, opts)
15        : ignore;
16/**
17 * basic walking utilities that all the glob walker types use
18 */
19class GlobUtil {
20    path;
21    patterns;
22    opts;
23    seen = new Set();
24    paused = false;
25    aborted = false;
26    #onResume = [];
27    #ignore;
28    #sep;
29    signal;
30    maxDepth;
31    includeChildMatches;
32    constructor(patterns, path, opts) {
33        this.patterns = patterns;
34        this.path = path;
35        this.opts = opts;
36        this.#sep = !opts.posix && opts.platform === 'win32' ? '\\' : '/';
37        this.includeChildMatches = opts.includeChildMatches !== false;
38        if (opts.ignore || !this.includeChildMatches) {
39            this.#ignore = makeIgnore(opts.ignore ?? [], opts);
40            if (!this.includeChildMatches &&
41                typeof this.#ignore.add !== 'function') {
42                const m = 'cannot ignore child matches, ignore lacks add() method.';
43                throw new Error(m);
44            }
45        }
46        // ignore, always set with maxDepth, but it's optional on the
47        // GlobOptions type
48        /* c8 ignore start */
49        this.maxDepth = opts.maxDepth || Infinity;
50        /* c8 ignore stop */
51        if (opts.signal) {
52            this.signal = opts.signal;
53            this.signal.addEventListener('abort', () => {
54                this.#onResume.length = 0;
55            });
56        }
57    }
58    #ignored(path) {
59        return this.seen.has(path) || !!this.#ignore?.ignored?.(path);
60    }
61    #childrenIgnored(path) {
62        return !!this.#ignore?.childrenIgnored?.(path);
63    }
64    // backpressure mechanism
65    pause() {
66        this.paused = true;
67    }
68    resume() {
69        /* c8 ignore start */
70        if (this.signal?.aborted)
71            return;
72        /* c8 ignore stop */
73        this.paused = false;
74        let fn = undefined;
75        while (!this.paused && (fn = this.#onResume.shift())) {
76            fn();
77        }
78    }
79    onResume(fn) {
80        if (this.signal?.aborted)
81            return;
82        /* c8 ignore start */
83        if (!this.paused) {
84            fn();
85        }
86        else {
87            /* c8 ignore stop */
88            this.#onResume.push(fn);
89        }
90    }
91    // do the requisite realpath/stat checking, and return the path
92    // to add or undefined to filter it out.
93    async matchCheck(e, ifDir) {
94        if (ifDir && this.opts.nodir)
95            return undefined;
96        let rpc;
97        if (this.opts.realpath) {
98            rpc = e.realpathCached() || (await e.realpath());
99            if (!rpc)
100                return undefined;
101            e = rpc;
102        }
103        const needStat = e.isUnknown() || this.opts.stat;
104        const s = needStat ? await e.lstat() : e;
105        if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
106            const target = await s.realpath();
107            /* c8 ignore start */
108            if (target && (target.isUnknown() || this.opts.stat)) {
109                await target.lstat();
110            }
111            /* c8 ignore stop */
112        }
113        return this.matchCheckTest(s, ifDir);
114    }
115    matchCheckTest(e, ifDir) {
116        return (e &&
117            (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&
118            (!ifDir || e.canReaddir()) &&
119            (!this.opts.nodir || !e.isDirectory()) &&
120            (!this.opts.nodir ||
121                !this.opts.follow ||
122                !e.isSymbolicLink() ||
123                !e.realpathCached()?.isDirectory()) &&
124            !this.#ignored(e)) ?
125            e
126            : undefined;
127    }
128    matchCheckSync(e, ifDir) {
129        if (ifDir && this.opts.nodir)
130            return undefined;
131        let rpc;
132        if (this.opts.realpath) {
133            rpc = e.realpathCached() || e.realpathSync();
134            if (!rpc)
135                return undefined;
136            e = rpc;
137        }
138        const needStat = e.isUnknown() || this.opts.stat;
139        const s = needStat ? e.lstatSync() : e;
140        if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
141            const target = s.realpathSync();
142            if (target && (target?.isUnknown() || this.opts.stat)) {
143                target.lstatSync();
144            }
145        }
146        return this.matchCheckTest(s, ifDir);
147    }
148    matchFinish(e, absolute) {
149        if (this.#ignored(e))
150            return;
151        // we know we have an ignore if this is false, but TS doesn't
152        if (!this.includeChildMatches && this.#ignore?.add) {
153            const ign = `${e.relativePosix()}/**`;
154            this.#ignore.add(ign);
155        }
156        const abs = this.opts.absolute === undefined ? absolute : this.opts.absolute;
157        this.seen.add(e);
158        const mark = this.opts.mark && e.isDirectory() ? this.#sep : '';
159        // ok, we have what we need!
160        if (this.opts.withFileTypes) {
161            this.matchEmit(e);
162        }
163        else if (abs) {
164            const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath();
165            this.matchEmit(abs + mark);
166        }
167        else {
168            const rel = this.opts.posix ? e.relativePosix() : e.relative();
169            const pre = this.opts.dotRelative && !rel.startsWith('..' + this.#sep) ?
170                '.' + this.#sep
171                : '';
172            this.matchEmit(!rel ? '.' + mark : pre + rel + mark);
173        }
174    }
175    async match(e, absolute, ifDir) {
176        const p = await this.matchCheck(e, ifDir);
177        if (p)
178            this.matchFinish(p, absolute);
179    }
180    matchSync(e, absolute, ifDir) {
181        const p = this.matchCheckSync(e, ifDir);
182        if (p)
183            this.matchFinish(p, absolute);
184    }
185    walkCB(target, patterns, cb) {
186        /* c8 ignore start */
187        if (this.signal?.aborted)
188            cb();
189        /* c8 ignore stop */
190        this.walkCB2(target, patterns, new processor_js_1.Processor(this.opts), cb);
191    }
192    walkCB2(target, patterns, processor, cb) {
193        if (this.#childrenIgnored(target))
194            return cb();
195        if (this.signal?.aborted)
196            cb();
197        if (this.paused) {
198            this.onResume(() => this.walkCB2(target, patterns, processor, cb));
199            return;
200        }
201        processor.processPatterns(target, patterns);
202        // done processing.  all of the above is sync, can be abstracted out.
203        // subwalks is a map of paths to the entry filters they need
204        // matches is a map of paths to [absolute, ifDir] tuples.
205        let tasks = 1;
206        const next = () => {
207            if (--tasks === 0)
208                cb();
209        };
210        for (const [m, absolute, ifDir] of processor.matches.entries()) {
211            if (this.#ignored(m))
212                continue;
213            tasks++;
214            this.match(m, absolute, ifDir).then(() => next());
215        }
216        for (const t of processor.subwalkTargets()) {
217            if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
218                continue;
219            }
220            tasks++;
221            const childrenCached = t.readdirCached();
222            if (t.calledReaddir())
223                this.walkCB3(t, childrenCached, processor, next);
224            else {
225                t.readdirCB((_, entries) => this.walkCB3(t, entries, processor, next), true);
226            }
227        }
228        next();
229    }
230    walkCB3(target, entries, processor, cb) {
231        processor = processor.filterEntries(target, entries);
232        let tasks = 1;
233        const next = () => {
234            if (--tasks === 0)
235                cb();
236        };
237        for (const [m, absolute, ifDir] of processor.matches.entries()) {
238            if (this.#ignored(m))
239                continue;
240            tasks++;
241            this.match(m, absolute, ifDir).then(() => next());
242        }
243        for (const [target, patterns] of processor.subwalks.entries()) {
244            tasks++;
245            this.walkCB2(target, patterns, processor.child(), next);
246        }
247        next();
248    }
249    walkCBSync(target, patterns, cb) {
250        /* c8 ignore start */
251        if (this.signal?.aborted)
252            cb();
253        /* c8 ignore stop */
254        this.walkCB2Sync(target, patterns, new processor_js_1.Processor(this.opts), cb);
255    }
256    walkCB2Sync(target, patterns, processor, cb) {
257        if (this.#childrenIgnored(target))
258            return cb();
259        if (this.signal?.aborted)
260            cb();
261        if (this.paused) {
262            this.onResume(() => this.walkCB2Sync(target, patterns, processor, cb));
263            return;
264        }
265        processor.processPatterns(target, patterns);
266        // done processing.  all of the above is sync, can be abstracted out.
267        // subwalks is a map of paths to the entry filters they need
268        // matches is a map of paths to [absolute, ifDir] tuples.
269        let tasks = 1;
270        const next = () => {
271            if (--tasks === 0)
272                cb();
273        };
274        for (const [m, absolute, ifDir] of processor.matches.entries()) {
275            if (this.#ignored(m))
276                continue;
277            this.matchSync(m, absolute, ifDir);
278        }
279        for (const t of processor.subwalkTargets()) {
280            if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
281                continue;
282            }
283            tasks++;
284            const children = t.readdirSync();
285            this.walkCB3Sync(t, children, processor, next);
286        }
287        next();
288    }
289    walkCB3Sync(target, entries, processor, cb) {
290        processor = processor.filterEntries(target, entries);
291        let tasks = 1;
292        const next = () => {
293            if (--tasks === 0)
294                cb();
295        };
296        for (const [m, absolute, ifDir] of processor.matches.entries()) {
297            if (this.#ignored(m))
298                continue;
299            this.matchSync(m, absolute, ifDir);
300        }
301        for (const [target, patterns] of processor.subwalks.entries()) {
302            tasks++;
303            this.walkCB2Sync(target, patterns, processor.child(), next);
304        }
305        next();
306    }
307}
308exports.GlobUtil = GlobUtil;
309class GlobWalker extends GlobUtil {
310    matches = new Set();
311    constructor(patterns, path, opts) {
312        super(patterns, path, opts);
313    }
314    matchEmit(e) {
315        this.matches.add(e);
316    }
317    async walk() {
318        if (this.signal?.aborted)
319            throw this.signal.reason;
320        if (this.path.isUnknown()) {
321            await this.path.lstat();
322        }
323        await new Promise((res, rej) => {
324            this.walkCB(this.path, this.patterns, () => {
325                if (this.signal?.aborted) {
326                    rej(this.signal.reason);
327                }
328                else {
329                    res(this.matches);
330                }
331            });
332        });
333        return this.matches;
334    }
335    walkSync() {
336        if (this.signal?.aborted)
337            throw this.signal.reason;
338        if (this.path.isUnknown()) {
339            this.path.lstatSync();
340        }
341        // nothing for the callback to do, because this never pauses
342        this.walkCBSync(this.path, this.patterns, () => {
343            if (this.signal?.aborted)
344                throw this.signal.reason;
345        });
346        return this.matches;
347    }
348}
349exports.GlobWalker = GlobWalker;
350class GlobStream extends GlobUtil {
351    results;
352    constructor(patterns, path, opts) {
353        super(patterns, path, opts);
354        this.results = new minipass_1.Minipass({
355            signal: this.signal,
356            objectMode: true,
357        });
358        this.results.on('drain', () => this.resume());
359        this.results.on('resume', () => this.resume());
360    }
361    matchEmit(e) {
362        this.results.write(e);
363        if (!this.results.flowing)
364            this.pause();
365    }
366    stream() {
367        const target = this.path;
368        if (target.isUnknown()) {
369            target.lstat().then(() => {
370                this.walkCB(target, this.patterns, () => this.results.end());
371            });
372        }
373        else {
374            this.walkCB(target, this.patterns, () => this.results.end());
375        }
376        return this.results;
377    }
378    streamSync() {
379        if (this.path.isUnknown()) {
380            this.path.lstatSync();
381        }
382        this.walkCBSync(this.path, this.patterns, () => this.results.end());
383        return this.results;
384    }
385}
386exports.GlobStream = GlobStream;
387//# sourceMappingURL=walker.js.map
codekingpro/portable-devtools · Team Ai