Ignore:
Timestamp:
09/19/26 10:30:30 (10 days ago)
Author:
Klimentina Efremova <klimentina08642@…>
Branches:
finki-main, main
Children:
06ebe74
Parents:
62b2964
Message:

Turned database from SQLite to PostgressSQL, updated database changes from Phase 1 and 2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • node_modules/minimatch/dist/esm/index.js

    r62b2964 r33517cc  
    1313};
    1414// Optimized checking for the most common glob patterns.
    15 const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
     15const starDotExtRE = /^\*+([^+@!?*[(]*)$/;
    1616const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
    1717const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
    … …  
    3232const starTest = (f) => f.length !== 0 && !f.startsWith('.');
    3333const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
    34 const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
     34const qmarksRE = /^\?+([^+@!?*[(]*)?$/;
    3535const qmarksTestNocase = ([$0, ext = '']) => {
    3636    const noext = qmarksTestNoExt([$0]);
    … …  
    194194    platform;
    195195    windowsNoMagicRoot;
     196    maxGlobstarRecursion;
    196197    regexp;
    197198    constructor(pattern, options = {}) {
    … …  
    199200        options = options || {};
    200201        this.options = options;
     202        this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200;
    201203        this.pattern = pattern;
    202204        this.platform = options.platform || defaultPlatform;
    … …  
    257259        this.globSet = [...new Set(this.braceExpand())];
    258260        if (options.debug) {
     261            //oxlint-disable-next-line no-console
    259262            this.debug = (...args) => console.error(...args);
    260263        }
    … …  
    319322        // if we're not in globstar mode, then turn ** into *
    320323        if (this.options.noglobstar) {
    321             for (let i = 0; i < globParts.length; i++) {
    322                 for (let j = 0; j < globParts[i].length; j++) {
    323                     if (globParts[i][j] === '**') {
    324                         globParts[i][j] = '*';
     324            for (const partset of globParts) {
     325                for (let j = 0; j < partset.length; j++) {
     326                    if (partset[j] === '**') {
     327                        partset[j] = '*';
    325328                    }
    326329                }
    … …  
    410413            while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
    411414                const p = parts[dd - 1];
    412                 if (p && p !== '.' && p !== '..' && p !== '**') {
     415                if (p &&
     416                    p !== '.' &&
     417                    p !== '..' &&
     418                    p !== '**' &&
     419                    !(this.isWindows && /^[a-z]:$/i.test(p))) {
    413420                    didSomething = true;
    414421                    parts.splice(dd - 1, 2);
    … …  
    603610    // the parts match.
    604611    matchOne(file, pattern, partial = false) {
    605         const options = this.options;
     612        let fileStartIndex = 0;
     613        let patternStartIndex = 0;
    606614        // UNC paths like //?/X:/... can match X:/... and vice versa
    607615        // Drive letters in absolute drive or unc paths are always compared
    … …  
    632640                    pattern[pdi],
    633641                ];
     642                // start matching at the drive letter index of each
    634643                if (fd.toLowerCase() === pd.toLowerCase()) {
    635644                    pattern[pdi] = fd;
    636                     if (pdi > fdi) {
    637                         pattern = pattern.slice(pdi);
    638                     }
    639                     else if (fdi > pdi) {
    640                         file = file.slice(fdi);
    641                     }
     645                    patternStartIndex = pdi;
     646                    fileStartIndex = fdi;
    642647                }
    643648            }
    … …  
    649654            file = this.levelTwoFileOptimize(file);
    650655        }
    651         this.debug('matchOne', this, { file, pattern });
    652         this.debug('matchOne', file.length, pattern.length);
    653         for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
     656        if (pattern.includes(GLOBSTAR)) {
     657            return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
     658        }
     659        return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
     660    }
     661    #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
     662        // split the pattern into head, tail, and middle of ** delimited parts
     663        const firstgs = pattern.indexOf(GLOBSTAR, patternIndex);
     664        const lastgs = pattern.lastIndexOf(GLOBSTAR);
     665        // split the pattern up into globstar-delimited sections
     666        // the tail has to be at the end, and the others just have
     667        // to be found in order from the head.
     668        const [head, body, tail] = partial ?
     669            [
     670                pattern.slice(patternIndex, firstgs),
     671                pattern.slice(firstgs + 1),
     672                [],
     673            ]
     674            : [
     675                pattern.slice(patternIndex, firstgs),
     676                pattern.slice(firstgs + 1, lastgs),
     677                pattern.slice(lastgs + 1),
     678            ];
     679        // check the head, from the current file/pattern index.
     680        if (head.length) {
     681            const fileHead = file.slice(fileIndex, fileIndex + head.length);
     682            if (!this.#matchOne(fileHead, head, partial, 0, 0)) {
     683                return false;
     684            }
     685            fileIndex += head.length;
     686            patternIndex += head.length;
     687        }
     688        // now we know the head matches!
     689        // if the last portion is not empty, it MUST match the end
     690        // check the tail
     691        let fileTailMatch = 0;
     692        if (tail.length) {
     693            // if head + tail > file, then we cannot possibly match
     694            if (tail.length + fileIndex > file.length)
     695                return false;
     696            // try to match the tail
     697            let tailStart = file.length - tail.length;
     698            if (this.#matchOne(file, tail, partial, tailStart, 0)) {
     699                fileTailMatch = tail.length;
     700            }
     701            else {
     702                // affordance for stuff like a/**/* matching a/b/
     703                // if the last file portion is '', and there's more to the pattern
     704                // then try without the '' bit.
     705                if (file[file.length - 1] !== '' ||
     706                    fileIndex + tail.length === file.length) {
     707                    return false;
     708                }
     709                tailStart--;
     710                if (!this.#matchOne(file, tail, partial, tailStart, 0)) {
     711                    return false;
     712                }
     713                fileTailMatch = tail.length + 1;
     714            }
     715        }
     716        // now we know the tail matches!
     717        // the middle is zero or more portions wrapped in **, possibly
     718        // containing more ** sections.
     719        // so a/**/b/**/c/**/d has become **/b/**/c/**
     720        // if it's empty, it means a/**/b, just verify we have no bad dots
     721        // if there's no tail, so it ends on /**, then we must have *something*
     722        // after the head, or it's not a matc
     723        if (!body.length) {
     724            let sawSome = !!fileTailMatch;
     725            for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
     726                const f = String(file[i]);
     727                sawSome = true;
     728                if (f === '.' ||
     729                    f === '..' ||
     730                    (!this.options.dot && f.startsWith('.'))) {
     731                    return false;
     732                }
     733            }
     734            // in partial mode, we just need to get past all file parts
     735            return partial || sawSome;
     736        }
     737        // now we know that there's one or more body sections, which can
     738        // be matched anywhere from the 0 index (because the head was pruned)
     739        // through to the length-fileTailMatch index.
     740        // split the body up into sections, and note the minimum index it can
     741        // be found at (start with the length of all previous segments)
     742        // [section, before, after]
     743        const bodySegments = [[[], 0]];
     744        let currentBody = bodySegments[0];
     745        let nonGsParts = 0;
     746        const nonGsPartsSums = [0];
     747        for (const b of body) {
     748            if (b === GLOBSTAR) {
     749                nonGsPartsSums.push(nonGsParts);
     750                currentBody = [[], 0];
     751                bodySegments.push(currentBody);
     752            }
     753            else {
     754                currentBody[0].push(b);
     755                nonGsParts++;
     756            }
     757        }
     758        let i = bodySegments.length - 1;
     759        const fileLength = file.length - fileTailMatch;
     760        for (const b of bodySegments) {
     761            b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length);
     762        }
     763        return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
     764    }
     765    // return false for "nope, not matching"
     766    // return null for "not matching, cannot keep trying"
     767    #matchGlobStarBodySections(file,
     768    // pattern section, last possible position for it
     769    bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
     770        // take the first body segment, and walk from fileIndex to its "after"
     771        // value at the end
     772        // If it doesn't match at that position, we increment, until we hit
     773        // that final possible position, and give up.
     774        // If it does match, then advance and try to rest.
     775        // If any of them fail we keep walking forward.
     776        // this is still a bit recursively painful, but it's more constrained
     777        // than previous implementations, because we never test something that
     778        // can't possibly be a valid matching condition.
     779        const bs = bodySegments[bodyIndex];
     780        if (!bs) {
     781            // just make sure that there's no bad dots
     782            for (let i = fileIndex; i < file.length; i++) {
     783                sawTail = true;
     784                const f = file[i];
     785                if (f === '.' ||
     786                    f === '..' ||
     787                    (!this.options.dot && f.startsWith('.'))) {
     788                    return false;
     789                }
     790            }
     791            return sawTail;
     792        }
     793        // have a non-globstar body section to test
     794        const [body, after] = bs;
     795        while (fileIndex <= after) {
     796            const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
     797            // if limit exceeded, no match. intentional false negative,
     798            // acceptable break in correctness for security.
     799            if (m && globStarDepth < this.maxGlobstarRecursion) {
     800                // match! see if the rest match. if so, we're done!
     801                const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
     802                if (sub !== false) {
     803                    return sub;
     804                }
     805            }
     806            const f = file[fileIndex];
     807            if (f === '.' ||
     808                f === '..' ||
     809                (!this.options.dot && f.startsWith('.'))) {
     810                return false;
     811            }
     812            fileIndex++;
     813        }
     814        // walked off. no point continuing
     815        return partial || null;
     816    }
     817    #matchOne(file, pattern, partial, fileIndex, patternIndex) {
     818        let fi;
     819        let pi;
     820        let pl;
     821        let fl;
     822        for (fi = fileIndex,
     823            pi = patternIndex,
     824            fl = file.length,
     825            pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
    654826            this.debug('matchOne loop');
    655             var p = pattern[pi];
    656             var f = file[fi];
     827            let p = pattern[pi];
     828            let f = file[fi];
    657829            this.debug(pattern, p, f);
    658830            // should be impossible.
    659831            // some invalid regexp stuff in the set.
    660832            /* c8 ignore start */
    661             if (p === false) {
     833            if (p === false || p === GLOBSTAR) {
    662834                return false;
    663835            }
    664836            /* c8 ignore stop */
    665             if (p === GLOBSTAR) {
    666                 this.debug('GLOBSTAR', [pattern, p, f]);
    667                 // "**"
    668                 // a/**/b/**/c would match the following:
    669                 // a/b/x/y/z/c
    670                 // a/x/y/z/b/c
    671                 // a/b/x/b/x/c
    672                 // a/b/c
    673                 // To do this, take the rest of the pattern after
    674                 // the **, and see if it would match the file remainder.
    675                 // If so, return success.
    676                 // If not, the ** "swallows" a segment, and try again.
    677                 // This is recursively awful.
    678                 //
    679                 // a/**/b/**/c matching a/b/x/y/z/c
    680                 // - a matches a
    681                 // - doublestar
    682                 //   - matchOne(b/x/y/z/c, b/**/c)
    683                 //     - b matches b
    684                 //     - doublestar
    685                 //       - matchOne(x/y/z/c, c) -> no
    686                 //       - matchOne(y/z/c, c) -> no
    687                 //       - matchOne(z/c, c) -> no
    688                 //       - matchOne(c, c) yes, hit
    689                 var fr = fi;
    690                 var pr = pi + 1;
    691                 if (pr === pl) {
    692                     this.debug('** at the end');
    693                     // a ** at the end will just swallow the rest.
    694                     // We have found a match.
    695                     // however, it will not swallow /.x, unless
    696                     // options.dot is set.
    697                     // . and .. are *never* matched by **, for explosively
    698                     // exponential reasons.
    699                     for (; fi < fl; fi++) {
    700                         if (file[fi] === '.' ||
    701                             file[fi] === '..' ||
    702                             (!options.dot && file[fi].charAt(0) === '.'))
    703                             return false;
    704                     }
    705                     return true;
    706                 }
    707                 // ok, let's see if we can swallow whatever we can.
    708                 while (fr < fl) {
    709                     var swallowee = file[fr];
    710                     this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
    711                     // XXX remove this slice.  Just pass the start index.
    712                     if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
    713                         this.debug('globstar found match!', fr, fl, swallowee);
    714                         // found a match.
    715                         return true;
    716                     }
    717                     else {
    718                         // can't swallow "." or ".." ever.
    719                         // can only swallow ".foo" when explicitly asked.
    720                         if (swallowee === '.' ||
    721                             swallowee === '..' ||
    722                             (!options.dot && swallowee.charAt(0) === '.')) {
    723                             this.debug('dot detected!', file, fr, pattern, pr);
    724                             break;
    725                         }
    726                         // ** swallows a segment, and continue.
    727                         this.debug('globstar swallow a segment, and continue');
    728                         fr++;
    729                     }
    730                 }
    731                 // no match was found.
    732                 // However, in partial mode, we can't say this is necessarily over.
    733                 /* c8 ignore start */
    734                 if (partial) {
    735                     // ran out of file
    736                     this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
    737                     if (fr === fl) {
    738                         return true;
    739                     }
    740                 }
    741                 /* c8 ignore stop */
    742                 return false;
    743             }
    744837            // something other than **
    745838            // non-magic patterns just have to match exactly
    … …  
    9291022            /* c8 ignore start */
    9301023        }
    931         catch (ex) {
     1024        catch {
    9321025            // should be impossible
    9331026            this.regexp = false;
    … …  
    9441037            return p.split('/');
    9451038        }
    946         else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
     1039        else if (this.isWindows && /^\/\/[^/]+/.test(p)) {
    9471040            // add an extra '' for the one we lose
    9481041            return ['', ...p.split(/\/+/)];
    … …  
    9861079            }
    9871080        }
    988         for (let i = 0; i < set.length; i++) {
    989             const pattern = set[i];
     1081        for (const pattern of set) {
    9901082            let file = ff;
    9911083            if (options.matchBase && pattern.length === 1) {
Note: See TracChangeset for help on using the changeset viewer.