Ignore:
Timestamp:
09/19/26 10:30:30 (11 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/commonjs/index.js

    r62b2964 r33517cc  
    1717exports.minimatch = minimatch;
    1818// Optimized checking for the most common glob patterns.
    19 const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
     19const starDotExtRE = /^\*+([^+@!?*[(]*)$/;
    2020const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
    2121const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
    … …  
    3636const starTest = (f) => f.length !== 0 && !f.startsWith('.');
    3737const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
    38 const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
     38const qmarksRE = /^\?+([^+@!?*[(]*)?$/;
    3939const qmarksTestNocase = ([$0, ext = '']) => {
    4040    const noext = qmarksTestNoExt([$0]);
    … …  
    203203    platform;
    204204    windowsNoMagicRoot;
     205    maxGlobstarRecursion;
    205206    regexp;
    206207    constructor(pattern, options = {}) {
    … …  
    208209        options = options || {};
    209210        this.options = options;
     211        this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200;
    210212        this.pattern = pattern;
    211213        this.platform = options.platform || defaultPlatform;
    … …  
    266268        this.globSet = [...new Set(this.braceExpand())];
    267269        if (options.debug) {
     270            //oxlint-disable-next-line no-console
    268271            this.debug = (...args) => console.error(...args);
    269272        }
    … …  
    328331        // if we're not in globstar mode, then turn ** into *
    329332        if (this.options.noglobstar) {
    330             for (let i = 0; i < globParts.length; i++) {
    331                 for (let j = 0; j < globParts[i].length; j++) {
    332                     if (globParts[i][j] === '**') {
    333                         globParts[i][j] = '*';
     333            for (const partset of globParts) {
     334                for (let j = 0; j < partset.length; j++) {
     335                    if (partset[j] === '**') {
     336                        partset[j] = '*';
    334337                    }
    335338                }
    … …  
    419422            while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
    420423                const p = parts[dd - 1];
    421                 if (p && p !== '.' && p !== '..' && p !== '**') {
     424                if (p &&
     425                    p !== '.' &&
     426                    p !== '..' &&
     427                    p !== '**' &&
     428                    !(this.isWindows && /^[a-z]:$/i.test(p))) {
    422429                    didSomething = true;
    423430                    parts.splice(dd - 1, 2);
    … …  
    612619    // the parts match.
    613620    matchOne(file, pattern, partial = false) {
    614         const options = this.options;
     621        let fileStartIndex = 0;
     622        let patternStartIndex = 0;
    615623        // UNC paths like //?/X:/... can match X:/... and vice versa
    616624        // Drive letters in absolute drive or unc paths are always compared
    … …  
    641649                    pattern[pdi],
    642650                ];
     651                // start matching at the drive letter index of each
    643652                if (fd.toLowerCase() === pd.toLowerCase()) {
    644653                    pattern[pdi] = fd;
    645                     if (pdi > fdi) {
    646                         pattern = pattern.slice(pdi);
    647                     }
    648                     else if (fdi > pdi) {
    649                         file = file.slice(fdi);
    650                     }
     654                    patternStartIndex = pdi;
     655                    fileStartIndex = fdi;
    651656                }
    652657            }
    … …  
    658663            file = this.levelTwoFileOptimize(file);
    659664        }
    660         this.debug('matchOne', this, { file, pattern });
    661         this.debug('matchOne', file.length, pattern.length);
    662         for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
     665        if (pattern.includes(exports.GLOBSTAR)) {
     666            return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
     667        }
     668        return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
     669    }
     670    #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
     671        // split the pattern into head, tail, and middle of ** delimited parts
     672        const firstgs = pattern.indexOf(exports.GLOBSTAR, patternIndex);
     673        const lastgs = pattern.lastIndexOf(exports.GLOBSTAR);
     674        // split the pattern up into globstar-delimited sections
     675        // the tail has to be at the end, and the others just have
     676        // to be found in order from the head.
     677        const [head, body, tail] = partial ?
     678            [
     679                pattern.slice(patternIndex, firstgs),
     680                pattern.slice(firstgs + 1),
     681                [],
     682            ]
     683            : [
     684                pattern.slice(patternIndex, firstgs),
     685                pattern.slice(firstgs + 1, lastgs),
     686                pattern.slice(lastgs + 1),
     687            ];
     688        // check the head, from the current file/pattern index.
     689        if (head.length) {
     690            const fileHead = file.slice(fileIndex, fileIndex + head.length);
     691            if (!this.#matchOne(fileHead, head, partial, 0, 0)) {
     692                return false;
     693            }
     694            fileIndex += head.length;
     695            patternIndex += head.length;
     696        }
     697        // now we know the head matches!
     698        // if the last portion is not empty, it MUST match the end
     699        // check the tail
     700        let fileTailMatch = 0;
     701        if (tail.length) {
     702            // if head + tail > file, then we cannot possibly match
     703            if (tail.length + fileIndex > file.length)
     704                return false;
     705            // try to match the tail
     706            let tailStart = file.length - tail.length;
     707            if (this.#matchOne(file, tail, partial, tailStart, 0)) {
     708                fileTailMatch = tail.length;
     709            }
     710            else {
     711                // affordance for stuff like a/**/* matching a/b/
     712                // if the last file portion is '', and there's more to the pattern
     713                // then try without the '' bit.
     714                if (file[file.length - 1] !== '' ||
     715                    fileIndex + tail.length === file.length) {
     716                    return false;
     717                }
     718                tailStart--;
     719                if (!this.#matchOne(file, tail, partial, tailStart, 0)) {
     720                    return false;
     721                }
     722                fileTailMatch = tail.length + 1;
     723            }
     724        }
     725        // now we know the tail matches!
     726        // the middle is zero or more portions wrapped in **, possibly
     727        // containing more ** sections.
     728        // so a/**/b/**/c/**/d has become **/b/**/c/**
     729        // if it's empty, it means a/**/b, just verify we have no bad dots
     730        // if there's no tail, so it ends on /**, then we must have *something*
     731        // after the head, or it's not a matc
     732        if (!body.length) {
     733            let sawSome = !!fileTailMatch;
     734            for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
     735                const f = String(file[i]);
     736                sawSome = true;
     737                if (f === '.' ||
     738                    f === '..' ||
     739                    (!this.options.dot && f.startsWith('.'))) {
     740                    return false;
     741                }
     742            }
     743            // in partial mode, we just need to get past all file parts
     744            return partial || sawSome;
     745        }
     746        // now we know that there's one or more body sections, which can
     747        // be matched anywhere from the 0 index (because the head was pruned)
     748        // through to the length-fileTailMatch index.
     749        // split the body up into sections, and note the minimum index it can
     750        // be found at (start with the length of all previous segments)
     751        // [section, before, after]
     752        const bodySegments = [[[], 0]];
     753        let currentBody = bodySegments[0];
     754        let nonGsParts = 0;
     755        const nonGsPartsSums = [0];
     756        for (const b of body) {
     757            if (b === exports.GLOBSTAR) {
     758                nonGsPartsSums.push(nonGsParts);
     759                currentBody = [[], 0];
     760                bodySegments.push(currentBody);
     761            }
     762            else {
     763                currentBody[0].push(b);
     764                nonGsParts++;
     765            }
     766        }
     767        let i = bodySegments.length - 1;
     768        const fileLength = file.length - fileTailMatch;
     769        for (const b of bodySegments) {
     770            b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length);
     771        }
     772        return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
     773    }
     774    // return false for "nope, not matching"
     775    // return null for "not matching, cannot keep trying"
     776    #matchGlobStarBodySections(file,
     777    // pattern section, last possible position for it
     778    bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
     779        // take the first body segment, and walk from fileIndex to its "after"
     780        // value at the end
     781        // If it doesn't match at that position, we increment, until we hit
     782        // that final possible position, and give up.
     783        // If it does match, then advance and try to rest.
     784        // If any of them fail we keep walking forward.
     785        // this is still a bit recursively painful, but it's more constrained
     786        // than previous implementations, because we never test something that
     787        // can't possibly be a valid matching condition.
     788        const bs = bodySegments[bodyIndex];
     789        if (!bs) {
     790            // just make sure that there's no bad dots
     791            for (let i = fileIndex; i < file.length; i++) {
     792                sawTail = true;
     793                const f = file[i];
     794                if (f === '.' ||
     795                    f === '..' ||
     796                    (!this.options.dot && f.startsWith('.'))) {
     797                    return false;
     798                }
     799            }
     800            return sawTail;
     801        }
     802        // have a non-globstar body section to test
     803        const [body, after] = bs;
     804        while (fileIndex <= after) {
     805            const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
     806            // if limit exceeded, no match. intentional false negative,
     807            // acceptable break in correctness for security.
     808            if (m && globStarDepth < this.maxGlobstarRecursion) {
     809                // match! see if the rest match. if so, we're done!
     810                const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
     811                if (sub !== false) {
     812                    return sub;
     813                }
     814            }
     815            const f = file[fileIndex];
     816            if (f === '.' ||
     817                f === '..' ||
     818                (!this.options.dot && f.startsWith('.'))) {
     819                return false;
     820            }
     821            fileIndex++;
     822        }
     823        // walked off. no point continuing
     824        return partial || null;
     825    }
     826    #matchOne(file, pattern, partial, fileIndex, patternIndex) {
     827        let fi;
     828        let pi;
     829        let pl;
     830        let fl;
     831        for (fi = fileIndex,
     832            pi = patternIndex,
     833            fl = file.length,
     834            pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
    663835            this.debug('matchOne loop');
    664             var p = pattern[pi];
    665             var f = file[fi];
     836            let p = pattern[pi];
     837            let f = file[fi];
    666838            this.debug(pattern, p, f);
    667839            // should be impossible.
    668840            // some invalid regexp stuff in the set.
    669841            /* c8 ignore start */
    670             if (p === false) {
     842            if (p === false || p === exports.GLOBSTAR) {
    671843                return false;
    672844            }
    673845            /* c8 ignore stop */
    674             if (p === exports.GLOBSTAR) {
    675                 this.debug('GLOBSTAR', [pattern, p, f]);
    676                 // "**"
    677                 // a/**/b/**/c would match the following:
    678                 // a/b/x/y/z/c
    679                 // a/x/y/z/b/c
    680                 // a/b/x/b/x/c
    681                 // a/b/c
    682                 // To do this, take the rest of the pattern after
    683                 // the **, and see if it would match the file remainder.
    684                 // If so, return success.
    685                 // If not, the ** "swallows" a segment, and try again.
    686                 // This is recursively awful.
    687                 //
    688                 // a/**/b/**/c matching a/b/x/y/z/c
    689                 // - a matches a
    690                 // - doublestar
    691                 //   - matchOne(b/x/y/z/c, b/**/c)
    692                 //     - b matches b
    693                 //     - doublestar
    694                 //       - matchOne(x/y/z/c, c) -> no
    695                 //       - matchOne(y/z/c, c) -> no
    696                 //       - matchOne(z/c, c) -> no
    697                 //       - matchOne(c, c) yes, hit
    698                 var fr = fi;
    699                 var pr = pi + 1;
    700                 if (pr === pl) {
    701                     this.debug('** at the end');
    702                     // a ** at the end will just swallow the rest.
    703                     // We have found a match.
    704                     // however, it will not swallow /.x, unless
    705                     // options.dot is set.
    706                     // . and .. are *never* matched by **, for explosively
    707                     // exponential reasons.
    708                     for (; fi < fl; fi++) {
    709                         if (file[fi] === '.' ||
    710                             file[fi] === '..' ||
    711                             (!options.dot && file[fi].charAt(0) === '.'))
    712                             return false;
    713                     }
    714                     return true;
    715                 }
    716                 // ok, let's see if we can swallow whatever we can.
    717                 while (fr < fl) {
    718                     var swallowee = file[fr];
    719                     this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
    720                     // XXX remove this slice.  Just pass the start index.
    721                     if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
    722                         this.debug('globstar found match!', fr, fl, swallowee);
    723                         // found a match.
    724                         return true;
    725                     }
    726                     else {
    727                         // can't swallow "." or ".." ever.
    728                         // can only swallow ".foo" when explicitly asked.
    729                         if (swallowee === '.' ||
    730                             swallowee === '..' ||
    731                             (!options.dot && swallowee.charAt(0) === '.')) {
    732                             this.debug('dot detected!', file, fr, pattern, pr);
    733                             break;
    734                         }
    735                         // ** swallows a segment, and continue.
    736                         this.debug('globstar swallow a segment, and continue');
    737                         fr++;
    738                     }
    739                 }
    740                 // no match was found.
    741                 // However, in partial mode, we can't say this is necessarily over.
    742                 /* c8 ignore start */
    743                 if (partial) {
    744                     // ran out of file
    745                     this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
    746                     if (fr === fl) {
    747                         return true;
    748                     }
    749                 }
    750                 /* c8 ignore stop */
    751                 return false;
    752             }
    753846            // something other than **
    754847            // non-magic patterns just have to match exactly
    … …  
    9381031            /* c8 ignore start */
    9391032        }
    940         catch (ex) {
     1033        catch {
    9411034            // should be impossible
    9421035            this.regexp = false;
    … …  
    9531046            return p.split('/');
    9541047        }
    955         else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
     1048        else if (this.isWindows && /^\/\/[^/]+/.test(p)) {
    9561049            // add an extra '' for the one we lose
    9571050            return ['', ...p.split(/\/+/)];
    … …  
    9951088            }
    9961089        }
    997         for (let i = 0; i < set.length; i++) {
    998             const pattern = set[i];
     1090        for (const pattern of set) {
    9991091            let file = ff;
    10001092            if (options.matchBase && pattern.length === 1) {
Note: See TracChangeset for help on using the changeset viewer.