Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
index.js2018 linesDownload Raw Back to commonjs
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3    if (k2 === undefined) k2 = k;
4    var desc = Object.getOwnPropertyDescriptor(m, k);
5    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6      desc = { enumerable: true, get: function() { return m[k]; } };
7    }
8    Object.defineProperty(o, k2, desc);
9}) : (function(o, m, k, k2) {
10    if (k2 === undefined) k2 = k;
11    o[k2] = m[k];
12}));
13var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14    Object.defineProperty(o, "default", { enumerable: true, value: v });
15}) : function(o, v) {
16    o["default"] = v;
17});
18var __importStar = (this && this.__importStar) || function (mod) {
19    if (mod && mod.__esModule) return mod;
20    var result = {};
21    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22    __setModuleDefault(result, mod);
23    return result;
24};
25Object.defineProperty(exports, "__esModule", { value: true });
26exports.PathScurry = exports.Path = exports.PathScurryDarwin = exports.PathScurryPosix = exports.PathScurryWin32 = exports.PathScurryBase = exports.PathPosix = exports.PathWin32 = exports.PathBase = exports.ChildrenCache = exports.ResolveCache = void 0;
27const lru_cache_1 = require("lru-cache");
28const node_path_1 = require("node:path");
29const node_url_1 = require("node:url");
30const fs_1 = require("fs");
31const actualFS = __importStar(require("node:fs"));
32const realpathSync = fs_1.realpathSync.native;
33// TODO: test perf of fs/promises realpath vs realpathCB,
34// since the promises one uses realpath.native
35const promises_1 = require("node:fs/promises");
36const minipass_1 = require("minipass");
37const defaultFS = {
38    lstatSync: fs_1.lstatSync,
39    readdir: fs_1.readdir,
40    readdirSync: fs_1.readdirSync,
41    readlinkSync: fs_1.readlinkSync,
42    realpathSync,
43    promises: {
44        lstat: promises_1.lstat,
45        readdir: promises_1.readdir,
46        readlink: promises_1.readlink,
47        realpath: promises_1.realpath,
48    },
49};
50// if they just gave us require('fs') then use our default
51const fsFromOption = (fsOption) => !fsOption || fsOption === defaultFS || fsOption === actualFS ?
52    defaultFS
53    : {
54        ...defaultFS,
55        ...fsOption,
56        promises: {
57            ...defaultFS.promises,
58            ...(fsOption.promises || {}),
59        },
60    };
61// turn something like //?/c:/ into c:\
62const uncDriveRegexp = /^\\\\\?\\([a-z]:)\\?$/i;
63const uncToDrive = (rootPath) => rootPath.replace(/\//g, '\\').replace(uncDriveRegexp, '$1\\');
64// windows paths are separated by either / or \
65const eitherSep = /[\\\/]/;
66const UNKNOWN = 0; // may not even exist, for all we know
67const IFIFO = 0b0001;
68const IFCHR = 0b0010;
69const IFDIR = 0b0100;
70const IFBLK = 0b0110;
71const IFREG = 0b1000;
72const IFLNK = 0b1010;
73const IFSOCK = 0b1100;
74const IFMT = 0b1111;
75// mask to unset low 4 bits
76const IFMT_UNKNOWN = ~IFMT;
77// set after successfully calling readdir() and getting entries.
78const READDIR_CALLED = 0b0000_0001_0000;
79// set after a successful lstat()
80const LSTAT_CALLED = 0b0000_0010_0000;
81// set if an entry (or one of its parents) is definitely not a dir
82const ENOTDIR = 0b0000_0100_0000;
83// set if an entry (or one of its parents) does not exist
84// (can also be set on lstat errors like EACCES or ENAMETOOLONG)
85const ENOENT = 0b0000_1000_0000;
86// cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK
87// set if we fail to readlink
88const ENOREADLINK = 0b0001_0000_0000;
89// set if we know realpath() will fail
90const ENOREALPATH = 0b0010_0000_0000;
91const ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH;
92const TYPEMASK = 0b0011_1111_1111;
93const entToType = (s) => s.isFile() ? IFREG
94    : s.isDirectory() ? IFDIR
95        : s.isSymbolicLink() ? IFLNK
96            : s.isCharacterDevice() ? IFCHR
97                : s.isBlockDevice() ? IFBLK
98                    : s.isSocket() ? IFSOCK
99                        : s.isFIFO() ? IFIFO
100                            : UNKNOWN;
101// normalize unicode path names
102const normalizeCache = new lru_cache_1.LRUCache({ max: 2 ** 12 });
103const normalize = (s) => {
104    const c = normalizeCache.get(s);
105    if (c)
106        return c;
107    const n = s.normalize('NFKD');
108    normalizeCache.set(s, n);
109    return n;
110};
111const normalizeNocaseCache = new lru_cache_1.LRUCache({ max: 2 ** 12 });
112const normalizeNocase = (s) => {
113    const c = normalizeNocaseCache.get(s);
114    if (c)
115        return c;
116    const n = normalize(s.toLowerCase());
117    normalizeNocaseCache.set(s, n);
118    return n;
119};
120/**
121 * An LRUCache for storing resolved path strings or Path objects.
122 * @internal
123 */
124class ResolveCache extends lru_cache_1.LRUCache {
125    constructor() {
126        super({ max: 256 });
127    }
128}
129exports.ResolveCache = ResolveCache;
130// In order to prevent blowing out the js heap by allocating hundreds of
131// thousands of Path entries when walking extremely large trees, the "children"
132// in this tree are represented by storing an array of Path entries in an
133// LRUCache, indexed by the parent.  At any time, Path.children() may return an
134// empty array, indicating that it doesn't know about any of its children, and
135// thus has to rebuild that cache.  This is fine, it just means that we don't
136// benefit as much from having the cached entries, but huge directory walks
137// don't blow out the stack, and smaller ones are still as fast as possible.
138//
139//It does impose some complexity when building up the readdir data, because we
140//need to pass a reference to the children array that we started with.
141/**
142 * an LRUCache for storing child entries.
143 * @internal
144 */
145class ChildrenCache extends lru_cache_1.LRUCache {
146    constructor(maxSize = 16 * 1024) {
147        super({
148            maxSize,
149            // parent + children
150            sizeCalculation: a => a.length + 1,
151        });
152    }
153}
154exports.ChildrenCache = ChildrenCache;
155const setAsCwd = Symbol('PathScurry setAsCwd');
156/**
157 * Path objects are sort of like a super-powered
158 * {@link https://nodejs.org/docs/latest/api/fs.html#class-fsdirent fs.Dirent}
159 *
160 * Each one represents a single filesystem entry on disk, which may or may not
161 * exist. It includes methods for reading various types of information via
162 * lstat, readlink, and readdir, and caches all information to the greatest
163 * degree possible.
164 *
165 * Note that fs operations that would normally throw will instead return an
166 * "empty" value. This is in order to prevent excessive overhead from error
167 * stack traces.
168 */
169class PathBase {
170    /**
171     * the basename of this path
172     *
173     * **Important**: *always* test the path name against any test string
174     * usingthe {@link isNamed} method, and not by directly comparing this
175     * string. Otherwise, unicode path strings that the system sees as identical
176     * will not be properly treated as the same path, leading to incorrect
177     * behavior and possible security issues.
178     */
179    name;
180    /**
181     * the Path entry corresponding to the path root.
182     *
183     * @internal
184     */
185    root;
186    /**
187     * All roots found within the current PathScurry family
188     *
189     * @internal
190     */
191    roots;
192    /**
193     * a reference to the parent path, or undefined in the case of root entries
194     *
195     * @internal
196     */
197    parent;
198    /**
199     * boolean indicating whether paths are compared case-insensitively
200     * @internal
201     */
202    nocase;
203    /**
204     * boolean indicating that this path is the current working directory
205     * of the PathScurry collection that contains it.
206     */
207    isCWD = false;
208    // potential default fs override
209    #fs;
210    // Stats fields
211    #dev;
212    get dev() {
213        return this.#dev;
214    }
215    #mode;
216    get mode() {
217        return this.#mode;
218    }
219    #nlink;
220    get nlink() {
221        return this.#nlink;
222    }
223    #uid;
224    get uid() {
225        return this.#uid;
226    }
227    #gid;
228    get gid() {
229        return this.#gid;
230    }
231    #rdev;
232    get rdev() {
233        return this.#rdev;
234    }
235    #blksize;
236    get blksize() {
237        return this.#blksize;
238    }
239    #ino;
240    get ino() {
241        return this.#ino;
242    }
243    #size;
244    get size() {
245        return this.#size;
246    }
247    #blocks;
248    get blocks() {
249        return this.#blocks;
250    }
251    #atimeMs;
252    get atimeMs() {
253        return this.#atimeMs;
254    }
255    #mtimeMs;
256    get mtimeMs() {
257        return this.#mtimeMs;
258    }
259    #ctimeMs;
260    get ctimeMs() {
261        return this.#ctimeMs;
262    }
263    #birthtimeMs;
264    get birthtimeMs() {
265        return this.#birthtimeMs;
266    }
267    #atime;
268    get atime() {
269        return this.#atime;
270    }
271    #mtime;
272    get mtime() {
273        return this.#mtime;
274    }
275    #ctime;
276    get ctime() {
277        return this.#ctime;
278    }
279    #birthtime;
280    get birthtime() {
281        return this.#birthtime;
282    }
283    #matchName;
284    #depth;
285    #fullpath;
286    #fullpathPosix;
287    #relative;
288    #relativePosix;
289    #type;
290    #children;
291    #linkTarget;
292    #realpath;
293    /**
294     * This property is for compatibility with the Dirent class as of
295     * Node v20, where Dirent['parentPath'] refers to the path of the
296     * directory that was passed to readdir. For root entries, it's the path
297     * to the entry itself.
298     */
299    get parentPath() {
300        return (this.parent || this).fullpath();
301    }
302    /* c8 ignore start */
303    /**
304     * Deprecated alias for Dirent['parentPath'] Somewhat counterintuitively,
305     * this property refers to the *parent* path, not the path object itself.
306     *
307     * @deprecated
308     */
309    get path() {
310        return this.parentPath;
311    }
312    /* c8 ignore stop */
313    /**
314     * Do not create new Path objects directly.  They should always be accessed
315     * via the PathScurry class or other methods on the Path class.
316     *
317     * @internal
318     */
319    constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
320        this.name = name;
321        this.#matchName = nocase ? normalizeNocase(name) : normalize(name);
322        this.#type = type & TYPEMASK;
323        this.nocase = nocase;
324        this.roots = roots;
325        this.root = root || this;
326        this.#children = children;
327        this.#fullpath = opts.fullpath;
328        this.#relative = opts.relative;
329        this.#relativePosix = opts.relativePosix;
330        this.parent = opts.parent;
331        if (this.parent) {
332            this.#fs = this.parent.#fs;
333        }
334        else {
335            this.#fs = fsFromOption(opts.fs);
336        }
337    }
338    /**
339     * Returns the depth of the Path object from its root.
340     *
341     * For example, a path at `/foo/bar` would have a depth of 2.
342     */
343    depth() {
344        if (this.#depth !== undefined)
345            return this.#depth;
346        if (!this.parent)
347            return (this.#depth = 0);
348        return (this.#depth = this.parent.depth() + 1);
349    }
350    /**
351     * @internal
352     */
353    childrenCache() {
354        return this.#children;
355    }
356    /**
357     * Get the Path object referenced by the string path, resolved from this Path
358     */
359    resolve(path) {
360        if (!path) {
361            return this;
362        }
363        const rootPath = this.getRootString(path);
364        const dir = path.substring(rootPath.length);
365        const dirParts = dir.split(this.splitSep);
366        const result = rootPath ?
367            this.getRoot(rootPath).#resolveParts(dirParts)
368            : this.#resolveParts(dirParts);
369        return result;
370    }
371    #resolveParts(dirParts) {
372        let p = this;
373        for (const part of dirParts) {
374            p = p.child(part);
375        }
376        return p;
377    }
378    /**
379     * Returns the cached children Path objects, if still available.  If they
380     * have fallen out of the cache, then returns an empty array, and resets the
381     * READDIR_CALLED bit, so that future calls to readdir() will require an fs
382     * lookup.
383     *
384     * @internal
385     */
386    children() {
387        const cached = this.#children.get(this);
388        if (cached) {
389            return cached;
390        }
391        const children = Object.assign([], { provisional: 0 });
392        this.#children.set(this, children);
393        this.#type &= ~READDIR_CALLED;
394        return children;
395    }
396    /**
397     * Resolves a path portion and returns or creates the child Path.
398     *
399     * Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is
400     * `'..'`.
401     *
402     * This should not be called directly.  If `pathPart` contains any path
403     * separators, it will lead to unsafe undefined behavior.
404     *
405     * Use `Path.resolve()` instead.
406     *
407     * @internal
408     */
409    child(pathPart, opts) {
410        if (pathPart === '' || pathPart === '.') {
411            return this;
412        }
413        if (pathPart === '..') {
414            return this.parent || this;
415        }
416        // find the child
417        const children = this.children();
418        const name = this.nocase ? normalizeNocase(pathPart) : normalize(pathPart);
419        for (const p of children) {
420            if (p.#matchName === name) {
421                return p;
422            }
423        }
424        // didn't find it, create provisional child, since it might not
425        // actually exist.  If we know the parent isn't a dir, then
426        // in fact it CAN'T exist.
427        const s = this.parent ? this.sep : '';
428        const fullpath = this.#fullpath ? this.#fullpath + s + pathPart : undefined;
429        const pchild = this.newChild(pathPart, UNKNOWN, {
430            ...opts,
431            parent: this,
432            fullpath,
433        });
434        if (!this.canReaddir()) {
435            pchild.#type |= ENOENT;
436        }
437        // don't have to update provisional, because if we have real children,
438        // then provisional is set to children.length, otherwise a lower number
439        children.push(pchild);
440        return pchild;
441    }
442    /**
443     * The relative path from the cwd. If it does not share an ancestor with
444     * the cwd, then this ends up being equivalent to the fullpath()
445     */
446    relative() {
447        if (this.isCWD)
448            return '';
449        if (this.#relative !== undefined) {
450            return this.#relative;
451        }
452        const name = this.name;
453        const p = this.parent;
454        if (!p) {
455            return (this.#relative = this.name);
456        }
457        const pv = p.relative();
458        return pv + (!pv || !p.parent ? '' : this.sep) + name;
459    }
460    /**
461     * The relative path from the cwd, using / as the path separator.
462     * If it does not share an ancestor with
463     * the cwd, then this ends up being equivalent to the fullpathPosix()
464     * On posix systems, this is identical to relative().
465     */
466    relativePosix() {
467        if (this.sep === '/')
468            return this.relative();
469        if (this.isCWD)
470            return '';
471        if (this.#relativePosix !== undefined)
472            return this.#relativePosix;
473        const name = this.name;
474        const p = this.parent;
475        if (!p) {
476            return (this.#relativePosix = this.fullpathPosix());
477        }
478        const pv = p.relativePosix();
479        return pv + (!pv || !p.parent ? '' : '/') + name;
480    }
481    /**
482     * The fully resolved path string for this Path entry
483     */
484    fullpath() {
485        if (this.#fullpath !== undefined) {
486            return this.#fullpath;
487        }
488        const name = this.name;
489        const p = this.parent;
490        if (!p) {
491            return (this.#fullpath = this.name);
492        }
493        const pv = p.fullpath();
494        const fp = pv + (!p.parent ? '' : this.sep) + name;
495        return (this.#fullpath = fp);
496    }
497    /**
498     * On platforms other than windows, this is identical to fullpath.
499     *
500     * On windows, this is overridden to return the forward-slash form of the
501     * full UNC path.
502     */
503    fullpathPosix() {
504        if (this.#fullpathPosix !== undefined)
505            return this.#fullpathPosix;
506        if (this.sep === '/')
507            return (this.#fullpathPosix = this.fullpath());
508        if (!this.parent) {
509            const p = this.fullpath().replace(/\\/g, '/');
510            if (/^[a-z]:\//i.test(p)) {
511                return (this.#fullpathPosix = `//?/${p}`);
512            }
513            else {
514                return (this.#fullpathPosix = p);
515            }
516        }
517        const p = this.parent;
518        const pfpp = p.fullpathPosix();
519        const fpp = pfpp + (!pfpp || !p.parent ? '' : '/') + this.name;
520        return (this.#fullpathPosix = fpp);
521    }
522    /**
523     * Is the Path of an unknown type?
524     *
525     * Note that we might know *something* about it if there has been a previous
526     * filesystem operation, for example that it does not exist, or is not a
527     * link, or whether it has child entries.
528     */
529    isUnknown() {
530        return (this.#type & IFMT) === UNKNOWN;
531    }
532    isType(type) {
533        return this[`is${type}`]();
534    }
535    getType() {
536        return (this.isUnknown() ? 'Unknown'
537            : this.isDirectory() ? 'Directory'
538                : this.isFile() ? 'File'
539                    : this.isSymbolicLink() ? 'SymbolicLink'
540                        : this.isFIFO() ? 'FIFO'
541                            : this.isCharacterDevice() ? 'CharacterDevice'
542                                : this.isBlockDevice() ? 'BlockDevice'
543                                    : /* c8 ignore start */ this.isSocket() ? 'Socket'
544                                        : 'Unknown');
545        /* c8 ignore stop */
546    }
547    /**
548     * Is the Path a regular file?
549     */
550    isFile() {
551        return (this.#type & IFMT) === IFREG;
552    }
553    /**
554     * Is the Path a directory?
555     */
556    isDirectory() {
557        return (this.#type & IFMT) === IFDIR;
558    }
559    /**
560     * Is the path a character device?
561     */
562    isCharacterDevice() {
563        return (this.#type & IFMT) === IFCHR;
564    }
565    /**
566     * Is the path a block device?
567     */
568    isBlockDevice() {
569        return (this.#type & IFMT) === IFBLK;
570    }
571    /**
572     * Is the path a FIFO pipe?
573     */
574    isFIFO() {
575        return (this.#type & IFMT) === IFIFO;
576    }
577    /**
578     * Is the path a socket?
579     */
580    isSocket() {
581        return (this.#type & IFMT) === IFSOCK;
582    }
583    /**
584     * Is the path a symbolic link?
585     */
586    isSymbolicLink() {
587        return (this.#type & IFLNK) === IFLNK;
588    }
589    /**
590     * Return the entry if it has been subject of a successful lstat, or
591     * undefined otherwise.
592     *
593     * Does not read the filesystem, so an undefined result *could* simply
594     * mean that we haven't called lstat on it.
595     */
596    lstatCached() {
597        return this.#type & LSTAT_CALLED ? this : undefined;
598    }
599    /**
600     * Return the cached link target if the entry has been the subject of a
601     * successful readlink, or undefined otherwise.
602     *
603     * Does not read the filesystem, so an undefined result *could* just mean we
604     * don't have any cached data. Only use it if you are very sure that a
605     * readlink() has been called at some point.
606     */
607    readlinkCached() {
608        return this.#linkTarget;
609    }
610    /**
611     * Returns the cached realpath target if the entry has been the subject
612     * of a successful realpath, or undefined otherwise.
613     *
614     * Does not read the filesystem, so an undefined result *could* just mean we
615     * don't have any cached data. Only use it if you are very sure that a
616     * realpath() has been called at some point.
617     */
618    realpathCached() {
619        return this.#realpath;
620    }
621    /**
622     * Returns the cached child Path entries array if the entry has been the
623     * subject of a successful readdir(), or [] otherwise.
624     *
625     * Does not read the filesystem, so an empty array *could* just mean we
626     * don't have any cached data. Only use it if you are very sure that a
627     * readdir() has been called recently enough to still be valid.
628     */
629    readdirCached() {
630        const children = this.children();
631        return children.slice(0, children.provisional);
632    }
633    /**
634     * Return true if it's worth trying to readlink.  Ie, we don't (yet) have
635     * any indication that readlink will definitely fail.
636     *
637     * Returns false if the path is known to not be a symlink, if a previous
638     * readlink failed, or if the entry does not exist.
639     */
640    canReadlink() {
641        if (this.#linkTarget)
642            return true;
643        if (!this.parent)
644            return false;
645        // cases where it cannot possibly succeed
646        const ifmt = this.#type & IFMT;
647        return !((ifmt !== UNKNOWN && ifmt !== IFLNK) ||
648            this.#type & ENOREADLINK ||
649            this.#type & ENOENT);
650    }
651    /**
652     * Return true if readdir has previously been successfully called on this
653     * path, indicating that cachedReaddir() is likely valid.
654     */
655    calledReaddir() {
656        return !!(this.#type & READDIR_CALLED);
657    }
658    /**
659     * Returns true if the path is known to not exist. That is, a previous lstat
660     * or readdir failed to verify its existence when that would have been
661     * expected, or a parent entry was marked either enoent or enotdir.
662     */
663    isENOENT() {
664        return !!(this.#type & ENOENT);
665    }
666    /**
667     * Return true if the path is a match for the given path name.  This handles
668     * case sensitivity and unicode normalization.
669     *
670     * Note: even on case-sensitive systems, it is **not** safe to test the
671     * equality of the `.name` property to determine whether a given pathname
672     * matches, due to unicode normalization mismatches.
673     *
674     * Always use this method instead of testing the `path.name` property
675     * directly.
676     */
677    isNamed(n) {
678        return !this.nocase ?
679            this.#matchName === normalize(n)
680            : this.#matchName === normalizeNocase(n);
681    }
682    /**
683     * Return the Path object corresponding to the target of a symbolic link.
684     *
685     * If the Path is not a symbolic link, or if the readlink call fails for any
686     * reason, `undefined` is returned.
687     *
688     * Result is cached, and thus may be outdated if the filesystem is mutated.
689     */
690    async readlink() {
691        const target = this.#linkTarget;
692        if (target) {
693            return target;
694        }
695        if (!this.canReadlink()) {
696            return undefined;
697        }
698        /* c8 ignore start */
699        // already covered by the canReadlink test, here for ts grumples
700        if (!this.parent) {
701            return undefined;
702        }
703        /* c8 ignore stop */
704        try {
705            const read = await this.#fs.promises.readlink(this.fullpath());
706            const linkTarget = (await this.parent.realpath())?.resolve(read);
707            if (linkTarget) {
708                return (this.#linkTarget = linkTarget);
709            }
710        }
711        catch (er) {
712            this.#readlinkFail(er.code);
713            return undefined;
714        }
715    }
716    /**
717     * Synchronous {@link PathBase.readlink}
718     */
719    readlinkSync() {
720        const target = this.#linkTarget;
721        if (target) {
722            return target;
723        }
724        if (!this.canReadlink()) {
725            return undefined;
726        }
727        /* c8 ignore start */
728        // already covered by the canReadlink test, here for ts grumples
729        if (!this.parent) {
730            return undefined;
731        }
732        /* c8 ignore stop */
733        try {
734            const read = this.#fs.readlinkSync(this.fullpath());
735            const linkTarget = this.parent.realpathSync()?.resolve(read);
736            if (linkTarget) {
737                return (this.#linkTarget = linkTarget);
738            }
739        }
740        catch (er) {
741            this.#readlinkFail(er.code);
742            return undefined;
743        }
744    }
745    #readdirSuccess(children) {
746        // succeeded, mark readdir called bit
747        this.#type |= READDIR_CALLED;
748        // mark all remaining provisional children as ENOENT
749        for (let p = children.provisional; p < children.length; p++) {
750            const c = children[p];
751            if (c)
752                c.#markENOENT();
753        }
754    }
755    #markENOENT() {
756        // mark as UNKNOWN and ENOENT
757        if (this.#type & ENOENT)
758            return;
759        this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN;
760        this.#markChildrenENOENT();
761    }
762    #markChildrenENOENT() {
763        // all children are provisional and do not exist
764        const children = this.children();
765        children.provisional = 0;
766        for (const p of children) {
767            p.#markENOENT();
768        }
769    }
770    #markENOREALPATH() {
771        this.#type |= ENOREALPATH;
772        this.#markENOTDIR();
773    }
774    // save the information when we know the entry is not a dir
775    #markENOTDIR() {
776        // entry is not a directory, so any children can't exist.
777        // this *should* be impossible, since any children created
778        // after it's been marked ENOTDIR should be marked ENOENT,
779        // so it won't even get to this point.
780        /* c8 ignore start */
781        if (this.#type & ENOTDIR)
782            return;
783        /* c8 ignore stop */
784        let t = this.#type;
785        // this could happen if we stat a dir, then delete it,
786        // then try to read it or one of its children.
787        if ((t & IFMT) === IFDIR)
788            t &= IFMT_UNKNOWN;
789        this.#type = t | ENOTDIR;
790        this.#markChildrenENOENT();
791    }
792    #readdirFail(code = '') {
793        // markENOTDIR and markENOENT also set provisional=0
794        if (code === 'ENOTDIR' || code === 'EPERM') {
795            this.#markENOTDIR();
796        }
797        else if (code === 'ENOENT') {
798            this.#markENOENT();
799        }
800        else {
801            this.children().provisional = 0;
802        }
803    }
804    #lstatFail(code = '') {
805        // Windows just raises ENOENT in this case, disable for win CI
806        /* c8 ignore start */
807        if (code === 'ENOTDIR') {
808            // already know it has a parent by this point
809            const p = this.parent;
810            p.#markENOTDIR();
811        }
812        else if (code === 'ENOENT') {
813            /* c8 ignore stop */
814            this.#markENOENT();
815        }
816    }
817    #readlinkFail(code = '') {
818        let ter = this.#type;
819        ter |= ENOREADLINK;
820        if (code === 'ENOENT')
821            ter |= ENOENT;
822        // windows gets a weird error when you try to readlink a file
823        if (code === 'EINVAL' || code === 'UNKNOWN') {
824            // exists, but not a symlink, we don't know WHAT it is, so remove
825            // all IFMT bits.
826            ter &= IFMT_UNKNOWN;
827        }
828        this.#type = ter;
829        // windows just gets ENOENT in this case.  We do cover the case,
830        // just disabled because it's impossible on Windows CI
831        /* c8 ignore start */
832        if (code === 'ENOTDIR' && this.parent) {
833            this.parent.#markENOTDIR();
834        }
835        /* c8 ignore stop */
836    }
837    #readdirAddChild(e, c) {
838        return (this.#readdirMaybePromoteChild(e, c) ||
839            this.#readdirAddNewChild(e, c));
840    }
841    #readdirAddNewChild(e, c) {
842        // alloc new entry at head, so it's never provisional
843        const type = entToType(e);
844        const child = this.newChild(e.name, type, { parent: this });
845        const ifmt = child.#type & IFMT;
846        if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) {
847            child.#type |= ENOTDIR;
848        }
849        c.unshift(child);
850        c.provisional++;
851        return child;
852    }
853    #readdirMaybePromoteChild(e, c) {
854        for (let p = c.provisional; p < c.length; p++) {
855            const pchild = c[p];
856            const name = this.nocase ? normalizeNocase(e.name) : normalize(e.name);
857            if (name !== pchild.#matchName) {
858                continue;
859            }
860            return this.#readdirPromoteChild(e, pchild, p, c);
861        }
862    }
863    #readdirPromoteChild(e, p, index, c) {
864        const v = p.name;
865        // retain any other flags, but set ifmt from dirent
866        p.#type = (p.#type & IFMT_UNKNOWN) | entToType(e);
867        // case sensitivity fixing when we learn the true name.
868        if (v !== e.name)
869            p.name = e.name;
870        // just advance provisional index (potentially off the list),
871        // otherwise we have to splice/pop it out and re-insert at head
872        if (index !== c.provisional) {
873            if (index === c.length - 1)
874                c.pop();
875            else
876                c.splice(index, 1);
877            c.unshift(p);
878        }
879        c.provisional++;
880        return p;
881    }
882    /**
883     * Call lstat() on this Path, and update all known information that can be
884     * determined.
885     *
886     * Note that unlike `fs.lstat()`, the returned value does not contain some
887     * information, such as `mode`, `dev`, `nlink`, and `ino`.  If that
888     * information is required, you will need to call `fs.lstat` yourself.
889     *
890     * If the Path refers to a nonexistent file, or if the lstat call fails for
891     * any reason, `undefined` is returned.  Otherwise the updated Path object is
892     * returned.
893     *
894     * Results are cached, and thus may be out of date if the filesystem is
895     * mutated.
896     */
897    async lstat() {
898        if ((this.#type & ENOENT) === 0) {
899            try {
900                this.#applyStat(await this.#fs.promises.lstat(this.fullpath()));
901                return this;
902            }
903            catch (er) {
904                this.#lstatFail(er.code);
905            }
906        }
907    }
908    /**
909     * synchronous {@link PathBase.lstat}
910     */
911    lstatSync() {
912        if ((this.#type & ENOENT) === 0) {
913            try {
914                this.#applyStat(this.#fs.lstatSync(this.fullpath()));
915                return this;
916            }
917            catch (er) {
918                this.#lstatFail(er.code);
919            }
920        }
921    }
922    #applyStat(st) {
923        const { atime, atimeMs, birthtime, birthtimeMs, blksize, blocks, ctime, ctimeMs, dev, gid, ino, mode, mtime, mtimeMs, nlink, rdev, size, uid, } = st;
924        this.#atime = atime;
925        this.#atimeMs = atimeMs;
926        this.#birthtime = birthtime;
927        this.#birthtimeMs = birthtimeMs;
928        this.#blksize = blksize;
929        this.#blocks = blocks;
930        this.#ctime = ctime;
931        this.#ctimeMs = ctimeMs;
932        this.#dev = dev;
933        this.#gid = gid;
934        this.#ino = ino;
935        this.#mode = mode;
936        this.#mtime = mtime;
937        this.#mtimeMs = mtimeMs;
938        this.#nlink = nlink;
939        this.#rdev = rdev;
940        this.#size = size;
941        this.#uid = uid;
942        const ifmt = entToType(st);
943        // retain any other flags, but set the ifmt
944        this.#type = (this.#type & IFMT_UNKNOWN) | ifmt | LSTAT_CALLED;
945        if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) {
946            this.#type |= ENOTDIR;
947        }
948    }
949    #onReaddirCB = [];
950    #readdirCBInFlight = false;
951    #callOnReaddirCB(children) {
952        this.#readdirCBInFlight = false;
953        const cbs = this.#onReaddirCB.slice();
954        this.#onReaddirCB.length = 0;
955        cbs.forEach(cb => cb(null, children));
956    }
957    /**
958     * Standard node-style callback interface to get list of directory entries.
959     *
960     * If the Path cannot or does not contain any children, then an empty array
961     * is returned.
962     *
963     * Results are cached, and thus may be out of date if the filesystem is
964     * mutated.
965     *
966     * @param cb The callback called with (er, entries).  Note that the `er`
967     * param is somewhat extraneous, as all readdir() errors are handled and
968     * simply result in an empty set of entries being returned.
969     * @param allowZalgo Boolean indicating that immediately known results should
970     * *not* be deferred with `queueMicrotask`. Defaults to `false`. Release
971     * zalgo at your peril, the dark pony lord is devious and unforgiving.
972     */
973    readdirCB(cb, allowZalgo = false) {
974        if (!this.canReaddir()) {
975            if (allowZalgo)
976                cb(null, []);
977            else
978                queueMicrotask(() => cb(null, []));
979            return;
980        }
981        const children = this.children();
982        if (this.calledReaddir()) {
983            const c = children.slice(0, children.provisional);
984            if (allowZalgo)
985                cb(null, c);
986            else
987                queueMicrotask(() => cb(null, c));
988            return;
989        }
990        // don't have to worry about zalgo at this point.
991        this.#onReaddirCB.push(cb);
992        if (this.#readdirCBInFlight) {
993            return;
994        }
995        this.#readdirCBInFlight = true;
996        // else read the directory, fill up children
997        // de-provisionalize any provisional children.
998        const fullpath = this.fullpath();
999        this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => {
1000            if (er) {
1001                this.#readdirFail(er.code);
1002                children.provisional = 0;
1003            }
1004            else {
1005                // if we didn't get an error, we always get entries.
1006                //@ts-ignore
1007                for (const e of entries) {
1008                    this.#readdirAddChild(e, children);
1009                }
1010                this.#readdirSuccess(children);
1011            }
1012            this.#callOnReaddirCB(children.slice(0, children.provisional));
1013            return;
1014        });
1015    }
1016    #asyncReaddirInFlight;
1017    /**
1018     * Return an array of known child entries.
1019     *
1020     * If the Path cannot or does not contain any children, then an empty array
1021     * is returned.
1022     *
1023     * Results are cached, and thus may be out of date if the filesystem is
1024     * mutated.
1025     */
1026    async readdir() {
1027        if (!this.canReaddir()) {
1028            return [];
1029        }
1030        const children = this.children();
1031        if (this.calledReaddir()) {
1032            return children.slice(0, children.provisional);
1033        }
1034        // else read the directory, fill up children
1035        // de-provisionalize any provisional children.
1036        const fullpath = this.fullpath();
1037        if (this.#asyncReaddirInFlight) {
1038            await this.#asyncReaddirInFlight;
1039        }
1040        else {
1041            /* c8 ignore start */
1042            let resolve = () => { };
1043            /* c8 ignore stop */
1044            this.#asyncReaddirInFlight = new Promise(res => (resolve = res));
1045            try {
1046                for (const e of await this.#fs.promises.readdir(fullpath, {
1047                    withFileTypes: true,
1048                })) {
1049                    this.#readdirAddChild(e, children);
1050                }
1051                this.#readdirSuccess(children);
1052            }
1053            catch (er) {
1054                this.#readdirFail(er.code);
1055                children.provisional = 0;
1056            }
1057            this.#asyncReaddirInFlight = undefined;
1058            resolve();
1059        }
1060        return children.slice(0, children.provisional);
1061    }
1062    /**
1063     * synchronous {@link PathBase.readdir}
1064     */
1065    readdirSync() {
1066        if (!this.canReaddir()) {
1067            return [];
1068        }
1069        const children = this.children();
1070        if (this.calledReaddir()) {
1071            return children.slice(0, children.provisional);
1072        }
1073        // else read the directory, fill up children
1074        // de-provisionalize any provisional children.
1075        const fullpath = this.fullpath();
1076        try {
1077            for (const e of this.#fs.readdirSync(fullpath, {
1078                withFileTypes: true,
1079            })) {
1080                this.#readdirAddChild(e, children);
1081            }
1082            this.#readdirSuccess(children);
1083        }
1084        catch (er) {
1085            this.#readdirFail(er.code);
1086            children.provisional = 0;
1087        }
1088        return children.slice(0, children.provisional);
1089    }
1090    canReaddir() {
1091        if (this.#type & ENOCHILD)
1092            return false;
1093        const ifmt = IFMT & this.#type;
1094        // we always set ENOTDIR when setting IFMT, so should be impossible
1095        /* c8 ignore start */
1096        if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) {
1097            return false;
1098        }
1099        /* c8 ignore stop */
1100        return true;
1101    }
1102    shouldWalk(dirs, walkFilter) {
1103        return ((this.#type & IFDIR) === IFDIR &&
1104            !(this.#type & ENOCHILD) &&
1105            !dirs.has(this) &&
1106            (!walkFilter || walkFilter(this)));
1107    }
1108    /**
1109     * Return the Path object corresponding to path as resolved
1110     * by realpath(3).
1111     *
1112     * If the realpath call fails for any reason, `undefined` is returned.
1113     *
1114     * Result is cached, and thus may be outdated if the filesystem is mutated.
1115     * On success, returns a Path object.
1116     */
1117    async realpath() {
1118        if (this.#realpath)
1119            return this.#realpath;
1120        if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
1121            return undefined;
1122        try {
1123            const rp = await this.#fs.promises.realpath(this.fullpath());
1124            return (this.#realpath = this.resolve(rp));
1125        }
1126        catch (_) {
1127            this.#markENOREALPATH();
1128        }
1129    }
1130    /**
1131     * Synchronous {@link realpath}
1132     */
1133    realpathSync() {
1134        if (this.#realpath)
1135            return this.#realpath;
1136        if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
1137            return undefined;
1138        try {
1139            const rp = this.#fs.realpathSync(this.fullpath());
1140            return (this.#realpath = this.resolve(rp));
1141        }
1142        catch (_) {
1143            this.#markENOREALPATH();
1144        }
1145    }
1146    /**
1147     * Internal method to mark this Path object as the scurry cwd,
1148     * called by {@link PathScurry#chdir}
1149     *
1150     * @internal
1151     */
1152    [setAsCwd](oldCwd) {
1153        if (oldCwd === this)
1154            return;
1155        oldCwd.isCWD = false;
1156        this.isCWD = true;
1157        const changed = new Set([]);
1158        let rp = [];
1159        let p = this;
1160        while (p && p.parent) {
1161            changed.add(p);
1162            p.#relative = rp.join(this.sep);
1163            p.#relativePosix = rp.join('/');
1164            p = p.parent;
1165            rp.push('..');
1166        }
1167        // now un-memoize parents of old cwd
1168        p = oldCwd;
1169        while (p && p.parent && !changed.has(p)) {
1170            p.#relative = undefined;
1171            p.#relativePosix = undefined;
1172            p = p.parent;
1173        }
1174    }
1175}
1176exports.PathBase = PathBase;
1177/**
1178 * Path class used on win32 systems
1179 *
1180 * Uses `'\\'` as the path separator for returned paths, either `'\\'` or `'/'`
1181 * as the path separator for parsing paths.
1182 */
1183class PathWin32 extends PathBase {
1184    /**
1185     * Separator for generating path strings.
1186     */
1187    sep = '\\';
1188    /**
1189     * Separator for parsing path strings.
1190     */
1191    splitSep = eitherSep;
1192    /**
1193     * Do not create new Path objects directly.  They should always be accessed
1194     * via the PathScurry class or other methods on the Path class.
1195     *
1196     * @internal
1197     */
1198    constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
1199        super(name, type, root, roots, nocase, children, opts);
1200    }

Showing the first 1,200 of 2018 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai