CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes45downloads
handler.js636 linesDownload Raw Back to chokidar
1"use strict";2Object.defineProperty(exports, "__esModule", { value: true });3exports.NodeFsHandler = exports.EVENTS = exports.isIBMi = exports.isFreeBSD = exports.isLinux = exports.isMacos = exports.isWindows = exports.IDENTITY_FN = exports.EMPTY_FN = exports.STR_CLOSE = exports.STR_END = exports.STR_DATA = void 0;4const fs_1 = require("fs");5const promises_1 = require("fs/promises");6const sysPath = require("path");7const os_1 = require("os");8exports.STR_DATA = 'data';9exports.STR_END = 'end';10exports.STR_CLOSE = 'close';11const EMPTY_FN = () => { };12exports.EMPTY_FN = EMPTY_FN;13const IDENTITY_FN = (val) => val;14exports.IDENTITY_FN = IDENTITY_FN;15const pl = process.platform;16exports.isWindows = pl === 'win32';17exports.isMacos = pl === 'darwin';18exports.isLinux = pl === 'linux';19exports.isFreeBSD = pl === 'freebsd';20exports.isIBMi = (0, os_1.type)() === 'OS400';21exports.EVENTS = {22    ALL: 'all',23    READY: 'ready',24    ADD: 'add',25    CHANGE: 'change',26    ADD_DIR: 'addDir',27    UNLINK: 'unlink',28    UNLINK_DIR: 'unlinkDir',29    RAW: 'raw',30    ERROR: 'error',31};32const EV = exports.EVENTS;33const THROTTLE_MODE_WATCH = 'watch';34const statMethods = { lstat: promises_1.lstat, stat: promises_1.stat };35const KEY_LISTENERS = 'listeners';36const KEY_ERR = 'errHandlers';37const KEY_RAW = 'rawEmitters';38const HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];39// prettier-ignore40const binaryExtensions = new Set([41    '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',42    'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',43    'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',44    'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',45    'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',46    'dtshd', 'dvb', 'dwg', 'dxf',47    'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',48    'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',49    'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',50    'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',51    'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',52    'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',53    'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',54    'mobi', 'mov', 'movie', 'mp3',55    'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',56    'nef', 'npx', 'numbers', 'nupkg',57    'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',58    'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',59    'potx', 'ppa', 'ppam',60    'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',61    'qt',62    'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',63    's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',64    'stl', 'suo', 'sub', 'swf',65    'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',66    'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',67    'viv', 'vob',68    'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',69    'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',70    'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',71    'xmind', 'xpi', 'xpm', 'xwd', 'xz',72    'z', 'zip', 'zipx',73]);74const isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());75// TODO: emit errors properly. Example: EMFILE on Macos.76const foreach = (val, fn) => {77    if (val instanceof Set) {78        val.forEach(fn);79    }80    else {81        fn(val);82    }83};84const addAndConvert = (main, prop, item) => {85    let container = main[prop];86    if (!(container instanceof Set)) {87        main[prop] = container = new Set([container]);88    }89    container.add(item);90};91const clearItem = (cont) => (key) => {92    const set = cont[key];93    if (set instanceof Set) {94        set.clear();95    }96    else {97        delete cont[key];98    }99};100const delFromSet = (main, prop, item) => {101    const container = main[prop];102    if (container instanceof Set) {103        container.delete(item);104    }105    else if (container === item) {106        delete main[prop];107    }108};109const isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);110const FsWatchInstances = new Map();111/**112 * Instantiates the fs_watch interface113 * @param path to be watched114 * @param options to be passed to fs_watch115 * @param listener main event handler116 * @param errHandler emits info about errors117 * @param emitRaw emits raw event data118 * @returns {NativeFsWatcher}119 */120function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {121    const handleEvent = (rawEvent, evPath) => {122        listener(path);123        emitRaw(rawEvent, evPath, { watchedPath: path });124        // emit based on events occurring for files from a directory's watcher in125        // case the file's watcher misses it (and rely on throttling to de-dupe)126        if (evPath && path !== evPath) {127            fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));128        }129    };130    try {131        return (0, fs_1.watch)(path, {132            persistent: options.persistent,133        }, handleEvent);134    }135    catch (error) {136        errHandler(error);137        return undefined;138    }139}140/**141 * Helper for passing fs_watch event data to a collection of listeners142 * @param fullPath absolute path bound to fs_watch instance143 */144const fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {145    const cont = FsWatchInstances.get(fullPath);146    if (!cont)147        return;148    foreach(cont[listenerType], (listener) => {149        listener(val1, val2, val3);150    });151};152/**153 * Instantiates the fs_watch interface or binds listeners154 * to an existing one covering the same file system entry155 * @param path156 * @param fullPath absolute path157 * @param options to be passed to fs_watch158 * @param handlers container for event listener functions159 */160const setFsWatchListener = (path, fullPath, options, handlers) => {161    const { listener, errHandler, rawEmitter } = handlers;162    let cont = FsWatchInstances.get(fullPath);163    let watcher;164    if (!options.persistent) {165        watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);166        if (!watcher)167            return;168        return watcher.close.bind(watcher);169    }170    if (cont) {171        addAndConvert(cont, KEY_LISTENERS, listener);172        addAndConvert(cont, KEY_ERR, errHandler);173        addAndConvert(cont, KEY_RAW, rawEmitter);174    }175    else {176        watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here177        fsWatchBroadcast.bind(null, fullPath, KEY_RAW));178        if (!watcher)179            return;180        watcher.on(EV.ERROR, async (error) => {181            const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);182            if (cont)183                cont.watcherUnusable = true; // documented since Node 10.4.1184            // Workaround for https://github.com/joyent/node/issues/4337185            if (exports.isWindows && error.code === 'EPERM') {186                try {187                    const fd = await (0, promises_1.open)(path, 'r');188                    await fd.close();189                    broadcastErr(error);190                }191                catch (err) {192                    // do nothing193                }194            }195            else {196                broadcastErr(error);197            }198        });199        cont = {200            listeners: listener,201            errHandlers: errHandler,202            rawEmitters: rawEmitter,203            watcher,204        };205        FsWatchInstances.set(fullPath, cont);206    }207    // const index = cont.listeners.indexOf(listener);208    // removes this instance's listeners and closes the underlying fs_watch209    // instance if there are no more listeners left210    return () => {211        delFromSet(cont, KEY_LISTENERS, listener);212        delFromSet(cont, KEY_ERR, errHandler);213        delFromSet(cont, KEY_RAW, rawEmitter);214        if (isEmptySet(cont.listeners)) {215            // Check to protect against issue gh-730.216            // if (cont.watcherUnusable) {217            cont.watcher.close();218            // }219            FsWatchInstances.delete(fullPath);220            HANDLER_KEYS.forEach(clearItem(cont));221            // @ts-ignore222            cont.watcher = undefined;223            Object.freeze(cont);224        }225    };226};227// fs_watchFile helpers228// object to hold per-process fs_watchFile instances229// (may be shared across chokidar FSWatcher instances)230const FsWatchFileInstances = new Map();231/**232 * Instantiates the fs_watchFile interface or binds listeners233 * to an existing one covering the same file system entry234 * @param path to be watched235 * @param fullPath absolute path236 * @param options options to be passed to fs_watchFile237 * @param handlers container for event listener functions238 * @returns closer239 */240const setFsWatchFileListener = (path, fullPath, options, handlers) => {241    const { listener, rawEmitter } = handlers;242    let cont = FsWatchFileInstances.get(fullPath);243    // let listeners = new Set();244    // let rawEmitters = new Set();245    const copts = cont && cont.options;246    if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {247        // "Upgrade" the watcher to persistence or a quicker interval.248        // This creates some unlikely edge case issues if the user mixes249        // settings in a very weird way, but solving for those cases250        // doesn't seem worthwhile for the added complexity.251        // listeners = cont.listeners;252        // rawEmitters = cont.rawEmitters;253        (0, fs_1.unwatchFile)(fullPath);254        cont = undefined;255    }256    if (cont) {257        addAndConvert(cont, KEY_LISTENERS, listener);258        addAndConvert(cont, KEY_RAW, rawEmitter);259    }260    else {261        // TODO262        // listeners.add(listener);263        // rawEmitters.add(rawEmitter);264        cont = {265            listeners: listener,266            rawEmitters: rawEmitter,267            options,268            watcher: (0, fs_1.watchFile)(fullPath, options, (curr, prev) => {269                foreach(cont.rawEmitters, (rawEmitter) => {270                    rawEmitter(EV.CHANGE, fullPath, { curr, prev });271                });272                const currmtime = curr.mtimeMs;273                if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {274                    foreach(cont.listeners, (listener) => listener(path, curr));275                }276            }),277        };278        FsWatchFileInstances.set(fullPath, cont);279    }280    // const index = cont.listeners.indexOf(listener);281    // Removes this instance's listeners and closes the underlying fs_watchFile282    // instance if there are no more listeners left.283    return () => {284        delFromSet(cont, KEY_LISTENERS, listener);285        delFromSet(cont, KEY_RAW, rawEmitter);286        if (isEmptySet(cont.listeners)) {287            FsWatchFileInstances.delete(fullPath);288            (0, fs_1.unwatchFile)(fullPath);289            cont.options = cont.watcher = undefined;290            Object.freeze(cont);291        }292    };293};294/**295 * @mixin296 */297class NodeFsHandler {298    constructor(fsW) {299        this.fsw = fsW;300        this._boundHandleError = (error) => fsW._handleError(error);301    }302    /**303     * Watch file for changes with fs_watchFile or fs_watch.304     * @param path to file or dir305     * @param listener on fs change306     * @returns closer for the watcher instance307     */308    _watchWithNodeFs(path, listener) {309        const opts = this.fsw.options;310        const directory = sysPath.dirname(path);311        const basename = sysPath.basename(path);312        const parent = this.fsw._getWatchedDir(directory);313        parent.add(basename);314        const absolutePath = sysPath.resolve(path);315        const options = {316            persistent: opts.persistent,317        };318        if (!listener)319            listener = exports.EMPTY_FN;320        let closer;321        if (opts.usePolling) {322            const enableBin = opts.interval !== opts.binaryInterval;323            options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;324            closer = setFsWatchFileListener(path, absolutePath, options, {325                listener,326                rawEmitter: this.fsw._emitRaw,327            });328        }329        else {330            closer = setFsWatchListener(path, absolutePath, options, {331                listener,332                errHandler: this._boundHandleError,333                rawEmitter: this.fsw._emitRaw,334            });335        }336        return closer;337    }338    /**339     * Watch a file and emit add event if warranted.340     * @returns closer for the watcher instance341     */342    _handleFile(file, stats, initialAdd) {343        if (this.fsw.closed) {344            return;345        }346        const dirname = sysPath.dirname(file);347        const basename = sysPath.basename(file);348        const parent = this.fsw._getWatchedDir(dirname);349        // stats is always present350        let prevStats = stats;351        // if the file is already being watched, do nothing352        if (parent.has(basename))353            return;354        const listener = async (path, newStats) => {355            if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))356                return;357            if (!newStats || newStats.mtimeMs === 0) {358                try {359                    const newStats = await (0, promises_1.stat)(file);360                    if (this.fsw.closed)361                        return;362                    // Check that change event was not fired because of changed only accessTime.363                    const at = newStats.atimeMs;364                    const mt = newStats.mtimeMs;365                    if (!at || at <= mt || mt !== prevStats.mtimeMs) {366                        this.fsw._emit(EV.CHANGE, file, newStats);367                    }368                    if ((exports.isMacos || exports.isLinux || exports.isFreeBSD) && prevStats.ino !== newStats.ino) {369                        this.fsw._closeFile(path);370                        prevStats = newStats;371                        const closer = this._watchWithNodeFs(file, listener);372                        if (closer)373                            this.fsw._addPathCloser(path, closer);374                    }375                    else {376                        prevStats = newStats;377                    }378                }379                catch (error) {380                    // Fix issues where mtime is null but file is still present381                    this.fsw._remove(dirname, basename);382                }383                // add is about to be emitted if file not already tracked in parent384            }385            else if (parent.has(basename)) {386                // Check that change event was not fired because of changed only accessTime.387                const at = newStats.atimeMs;388                const mt = newStats.mtimeMs;389                if (!at || at <= mt || mt !== prevStats.mtimeMs) {390                    this.fsw._emit(EV.CHANGE, file, newStats);391                }392                prevStats = newStats;393            }394        };395        // kick off the watcher396        const closer = this._watchWithNodeFs(file, listener);397        // emit an add event if we're supposed to398        if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {399            if (!this.fsw._throttle(EV.ADD, file, 0))400                return;401            this.fsw._emit(EV.ADD, file, stats);402        }403        return closer;404    }405    /**406     * Handle symlinks encountered while reading a dir.407     * @param entry returned by readdirp408     * @param directory path of dir being read409     * @param path of this item410     * @param item basename of this item411     * @returns true if no more processing is needed for this entry.412     */413    async _handleSymlink(entry, directory, path, item) {414        if (this.fsw.closed) {415            return;416        }417        const full = entry.fullPath;418        const dir = this.fsw._getWatchedDir(directory);419        if (!this.fsw.options.followSymlinks) {420            // watch symlink directly (don't follow) and detect changes421            this.fsw._incrReadyCount();422            let linkPath;423            try {424                linkPath = await (0, promises_1.realpath)(path);425            }426            catch (e) {427                this.fsw._emitReady();428                return true;429            }430            if (this.fsw.closed)431                return;432            if (dir.has(item)) {433                if (this.fsw._symlinkPaths.get(full) !== linkPath) {434                    this.fsw._symlinkPaths.set(full, linkPath);435                    this.fsw._emit(EV.CHANGE, path, entry.stats);436                }437            }438            else {439                dir.add(item);440                this.fsw._symlinkPaths.set(full, linkPath);441                this.fsw._emit(EV.ADD, path, entry.stats);442            }443            this.fsw._emitReady();444            return true;445        }446        // don't follow the same symlink more than once447        if (this.fsw._symlinkPaths.has(full)) {448            return true;449        }450        this.fsw._symlinkPaths.set(full, true);451    }452    _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {453        // Normalize the directory name on Windows454        directory = sysPath.join(directory, '');455        throttler = this.fsw._throttle('readdir', directory, 1000);456        if (!throttler)457            return;458        const previous = this.fsw._getWatchedDir(wh.path);459        const current = new Set();460        let stream = this.fsw._readdirp(directory, {461            fileFilter: (entry) => wh.filterPath(entry),462            directoryFilter: (entry) => wh.filterDir(entry),463        });464        if (!stream)465            return;466        stream467            .on(exports.STR_DATA, async (entry) => {468            if (this.fsw.closed) {469                stream = undefined;470                return;471            }472            const item = entry.path;473            let path = sysPath.join(directory, item);474            current.add(item);475            if (entry.stats.isSymbolicLink() &&476                (await this._handleSymlink(entry, directory, path, item))) {477                return;478            }479            if (this.fsw.closed) {480                stream = undefined;481                return;482            }483            // Files that present in current directory snapshot484            // but absent in previous are added to watch list and485            // emit `add` event.486            if (item === target || (!target && !previous.has(item))) {487                this.fsw._incrReadyCount();488                // ensure relativeness of path is preserved in case of watcher reuse489                path = sysPath.join(dir, sysPath.relative(dir, path));490                this._addToNodeFs(path, initialAdd, wh, depth + 1);491            }492        })493            .on(EV.ERROR, this._boundHandleError);494        return new Promise((resolve, reject) => {495            if (!stream)496                return reject();497            stream.once(exports.STR_END, () => {498                if (this.fsw.closed) {499                    stream = undefined;500                    return;501                }502                const wasThrottled = throttler ? throttler.clear() : false;503                resolve(undefined);504                // Files that absent in current directory snapshot505                // but present in previous emit `remove` event506                // and are removed from @watched[directory].507                previous508                    .getChildren()509                    .filter((item) => {510                    return item !== directory && !current.has(item);511                })512                    .forEach((item) => {513                    this.fsw._remove(directory, item);514                });515                stream = undefined;516                // one more time for any missed in case changes came in extremely quickly517                if (wasThrottled)518                    this._handleRead(directory, false, wh, target, dir, depth, throttler);519            });520        });521    }522    /**523     * Read directory to add / remove files from `@watched` list and re-read it on change.524     * @param dir fs path525     * @param stats526     * @param initialAdd527     * @param depth relative to user-supplied path528     * @param target child path targeted for watch529     * @param wh Common watch helpers for this path530     * @param realpath531     * @returns closer for the watcher instance.532     */533    async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {534        const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));535        const tracked = parentDir.has(sysPath.basename(dir));536        if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {537            this.fsw._emit(EV.ADD_DIR, dir, stats);538        }539        // ensure dir is tracked (harmless if redundant)540        parentDir.add(sysPath.basename(dir));541        this.fsw._getWatchedDir(dir);542        let throttler;543        let closer;544        const oDepth = this.fsw.options.depth;545        if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {546            if (!target) {547                await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);548                if (this.fsw.closed)549                    return;550            }551            closer = this._watchWithNodeFs(dir, (dirPath, stats) => {552                // if current directory is removed, do nothing553                if (stats && stats.mtimeMs === 0)554                    return;555                this._handleRead(dirPath, false, wh, target, dir, depth, throttler);556            });557        }558        return closer;559    }560    /**561     * Handle added file, directory, or glob pattern.562     * Delegates call to _handleFile / _handleDir after checks.563     * @param path to file or ir564     * @param initialAdd was the file added at watch instantiation?565     * @param priorWh depth relative to user-supplied path566     * @param depth Child path actually targeted for watch567     * @param target Child path actually targeted for watch568     */569    async _addToNodeFs(path, initialAdd, priorWh, depth, target) {570        const ready = this.fsw._emitReady;571        if (this.fsw._isIgnored(path) || this.fsw.closed) {572            ready();573            return false;574        }575        const wh = this.fsw._getWatchHelpers(path);576        if (priorWh) {577            wh.filterPath = (entry) => priorWh.filterPath(entry);578            wh.filterDir = (entry) => priorWh.filterDir(entry);579        }580        // evaluate what is at the path we're being asked to watch581        try {582            const stats = await statMethods[wh.statMethod](wh.watchPath);583            if (this.fsw.closed)584                return;585            if (this.fsw._isIgnored(wh.watchPath, stats)) {586                ready();587                return false;588            }589            const follow = this.fsw.options.followSymlinks;590            let closer;591            if (stats.isDirectory()) {592                const absPath = sysPath.resolve(path);593                const targetPath = follow ? await (0, promises_1.realpath)(path) : path;594                if (this.fsw.closed)595                    return;596                closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);597                if (this.fsw.closed)598                    return;599                // preserve this symlink's target path600                if (absPath !== targetPath && targetPath !== undefined) {601                    this.fsw._symlinkPaths.set(absPath, targetPath);602                }603            }604            else if (stats.isSymbolicLink()) {605                const targetPath = follow ? await (0, promises_1.realpath)(path) : path;606                if (this.fsw.closed)607                    return;608                const parent = sysPath.dirname(wh.watchPath);609                this.fsw._getWatchedDir(parent).add(wh.watchPath);610                this.fsw._emit(EV.ADD, wh.watchPath, stats);611                closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);612                if (this.fsw.closed)613                    return;614                // preserve this symlink's target path615                if (targetPath !== undefined) {616                    this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);617                }618            }619            else {620                closer = this._handleFile(wh.watchPath, stats, initialAdd);621            }622            ready();623            if (closer)624                this.fsw._addPathCloser(path, closer);625            return false;626        }627        catch (error) {628            if (this.fsw._handleError(error)) {629                ready();630                return path;631            }632        }633    }634}635exports.NodeFsHandler = NodeFsHandler;636 
basant307/AI_Governance_Project · CoolFace