From e4347a4b2389532d46d3ed26a2bab56cf7024ba7 Mon Sep 17 00:00:00 2001 From: Lars Kappert Date: Wed, 30 Oct 2024 13:20:04 +0100 Subject: [PATCH 1/3] Patch picomatch --- package.json | 7 ++++++- patches/picomatch@4.0.2.patch | 27 +++++++++++++++++++++++++++ pnpm-lock.yaml | 19 ++++++++++++------- 3 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 patches/picomatch@4.0.2.patch diff --git a/package.json b/package.json index b363a09..d851a51 100644 --- a/package.json +++ b/package.json @@ -62,5 +62,10 @@ "access": "public", "provenance": true }, - "packageManager": "pnpm@10.4.1" + "packageManager": "pnpm@10.4.1", + "pnpm": { + "patchedDependencies": { + "picomatch@4.0.2": "patches/picomatch@4.0.2.patch" + } + } } diff --git a/patches/picomatch@4.0.2.patch b/patches/picomatch@4.0.2.patch new file mode 100644 index 0000000..4b3cb91 --- /dev/null +++ b/patches/picomatch@4.0.2.patch @@ -0,0 +1,27 @@ +diff --git a/lib/picomatch.js b/lib/picomatch.js +index d0ebd9f163cf240a00998dec9ed69523d1405b4d..b5d9fb5b0f55b70f99a5012b80e91974b46699eb 100644 +--- a/lib/picomatch.js ++++ b/lib/picomatch.js +@@ -75,12 +75,17 @@ const picomatch = (glob, options, returnState = false) => { + return returnObject ? result : false; + } + +- if (isIgnored(input)) { +- if (typeof opts.onIgnore === 'function') { +- opts.onIgnore(result); ++ ignored: { ++ if (isIgnored(input)) { ++ if (typeof opts.onIgnore === 'function') { ++ if (opts.onIgnore(result) === true) { ++ result.isMatch = true; ++ break ignored; ++ } ++ } ++ result.isMatch = false; ++ return returnObject ? result : false; + } +- result.isMatch = false; +- return returnObject ? result : false; + } + + if (typeof opts.onMatch === 'function') { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1e0597..22f8769 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,16 +4,21 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + picomatch@4.0.2: + hash: be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805 + path: patches/picomatch@4.0.2.patch + importers: .: dependencies: fdir: specifier: ^6.4.3 - version: 6.4.3(picomatch@4.0.2) + version: 6.4.3(picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805)) picomatch: specifier: ^4.0.2 - version: 4.0.2 + version: 4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805) devDependencies: '@biomejs/biome': specifier: ^1.9.4 @@ -977,9 +982,9 @@ snapshots: '@esbuild/win32-ia32': 0.24.2 '@esbuild/win32-x64': 0.24.2 - fdir@6.4.3(picomatch@4.0.2): + fdir@6.4.3(picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805)): optionalDependencies: - picomatch: 4.0.2 + picomatch: 4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805) foreground-child@3.3.0: dependencies: @@ -1049,7 +1054,7 @@ snapshots: picocolors@1.1.1: {} - picomatch@4.0.2: {} + picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805): {} pirates@4.0.6: {} @@ -1142,8 +1147,8 @@ snapshots: tinyglobby@0.2.10: dependencies: - fdir: 6.4.3(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.4.3(picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805)) + picomatch: 4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805) tr46@1.0.1: dependencies: From f15ca045c85da3b0eb2dd54976d16064bf9f93a7 Mon Sep 17 00:00:00 2001 From: Lars Kappert Date: Wed, 30 Oct 2024 13:21:13 +0100 Subject: [PATCH 2/3] Support negative ignore patterns --- src/index.ts | 11 ++++++++--- test/index.test.ts | 4 +--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9def92f..e6932f6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -106,14 +106,16 @@ function processPatterns( const matchPatterns: string[] = []; const ignorePatterns: string[] = []; + const unignorePatterns: string[] = []; for (const pattern of ignore) { if (!pattern) { continue; } - // don't handle negated patterns here for consistency with fast-glob if (pattern[0] !== '!' || pattern[1] === '(') { ignorePatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, true)); + } else { + unignorePatterns.push(pattern.slice(1)); } } @@ -128,7 +130,7 @@ function processPatterns( } } - return { match: matchPatterns, ignore: ignorePatterns }; + return { match: matchPatterns, ignore: ignorePatterns, unignore: unignorePatterns }; } // TODO: this is slow, find a better way to do this @@ -182,10 +184,13 @@ function crawl(options: GlobOptions, cwd: string, sync: boolean) { log('internal processing patterns:', processed); } + const unignoreMatcher = processed.unignore.length === 0 ? undefined : picomatch(processed.unignore); + const matcher = picomatch(processed.match, { dot: options.dot, nocase, - ignore: processed.ignore + ignore: processed.ignore, + onIgnore: unignoreMatcher ? result => unignoreMatcher(result.output) : undefined }); const ignore = picomatch(processed.ignore, { diff --git a/test/index.test.ts b/test/index.test.ts index f91125b..9f9d4e9 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -352,11 +352,9 @@ test('negative absolute patterns in options', async () => { assert.deepEqual(files2.sort(), ['a/b.txt', 'b/b.txt']); }); -// can't easily make them properly work right now -// but at least it's consistent with fast-glob this way test('negative patterns in ignore are ignored', async () => { const files = await glob({ patterns: ['**/*'], ignore: ['**/b.txt', '!a/b.txt'], cwd }); - assert.deepEqual(files.sort(), ['a/a.txt', 'b/a.txt']); + assert.deepEqual(files.sort(), ['a/a.txt', 'a/b.txt', 'b/a.txt']); const files2 = await glob({ patterns: ['**/*', '!**/b.txt', '!!a/b.txt'], cwd }); assert.deepEqual(files2.sort(), ['a/a.txt', 'b/a.txt']); From b603afc08f406bf93a72ab6a4ecf0936af42b7d8 Mon Sep 17 00:00:00 2001 From: Lars Kappert Date: Sun, 15 Dec 2024 08:04:59 +0100 Subject: [PATCH 3/3] =?UTF-8?q?picomatch=20patch=20=E2=86=92=20unmatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 10 ++-------- patches/picomatch@4.0.2.patch | 27 ------------------------- pnpm-lock.yaml | 37 ++++++++++++++--------------------- src/index.ts | 10 +++++----- src/utils.ts | 8 ++++---- 5 files changed, 26 insertions(+), 66 deletions(-) delete mode 100644 patches/picomatch@4.0.2.patch diff --git a/package.json b/package.json index d851a51..474d3ed 100644 --- a/package.json +++ b/package.json @@ -45,12 +45,11 @@ }, "dependencies": { "fdir": "^6.4.3", - "picomatch": "^4.0.2" + "unmatch": "^1.0.1" }, "devDependencies": { "@biomejs/biome": "^1.9.4", "@types/node": "^22.13.4", - "@types/picomatch": "^3.0.2", "fs-fixture": "^2.7.0", "tsup": "^8.3.6", "typescript": "^5.7.3" @@ -62,10 +61,5 @@ "access": "public", "provenance": true }, - "packageManager": "pnpm@10.4.1", - "pnpm": { - "patchedDependencies": { - "picomatch@4.0.2": "patches/picomatch@4.0.2.patch" - } - } + "packageManager": "pnpm@10.4.1" } diff --git a/patches/picomatch@4.0.2.patch b/patches/picomatch@4.0.2.patch deleted file mode 100644 index 4b3cb91..0000000 --- a/patches/picomatch@4.0.2.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/lib/picomatch.js b/lib/picomatch.js -index d0ebd9f163cf240a00998dec9ed69523d1405b4d..b5d9fb5b0f55b70f99a5012b80e91974b46699eb 100644 ---- a/lib/picomatch.js -+++ b/lib/picomatch.js -@@ -75,12 +75,17 @@ const picomatch = (glob, options, returnState = false) => { - return returnObject ? result : false; - } - -- if (isIgnored(input)) { -- if (typeof opts.onIgnore === 'function') { -- opts.onIgnore(result); -+ ignored: { -+ if (isIgnored(input)) { -+ if (typeof opts.onIgnore === 'function') { -+ if (opts.onIgnore(result) === true) { -+ result.isMatch = true; -+ break ignored; -+ } -+ } -+ result.isMatch = false; -+ return returnObject ? result : false; - } -- result.isMatch = false; -- return returnObject ? result : false; - } - - if (typeof opts.onMatch === 'function') { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22f8769..31311f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,21 +4,16 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -patchedDependencies: - picomatch@4.0.2: - hash: be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805 - path: patches/picomatch@4.0.2.patch - importers: .: dependencies: fdir: specifier: ^6.4.3 - version: 6.4.3(picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805)) - picomatch: - specifier: ^4.0.2 - version: 4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805) + version: 6.4.3(picomatch@4.0.2) + unmatch: + specifier: ^1.0.1 + version: 1.0.1 devDependencies: '@biomejs/biome': specifier: ^1.9.4 @@ -26,9 +21,6 @@ importers: '@types/node': specifier: ^22.13.4 version: 22.13.4 - '@types/picomatch': - specifier: ^3.0.2 - version: 3.0.2 fs-fixture: specifier: ^2.7.0 version: 2.7.0 @@ -371,9 +363,6 @@ packages: '@types/node@22.13.4': resolution: {integrity: sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==} - '@types/picomatch@3.0.2': - resolution: {integrity: sha512-n0i8TD3UDB7paoMMxA3Y65vUncFJXjcUf7lQY7YyKGl6031FNjfsLs6pdLFCy2GNFxItPJG8GvvpbZc2skH7WA==} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -674,6 +663,10 @@ packages: undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + unmatch@1.0.1: + resolution: {integrity: sha512-Fe6Mi4RUci7pappunyfLbU0m+vq4xNkgjXXMmMzv58F3hQs3N4fg1oiAeGE7P6O8y6g+ck3RpbMn5CiLTHHysQ==} + engines: {node: '>=12'} + webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} @@ -897,8 +890,6 @@ snapshots: dependencies: undici-types: 6.20.0 - '@types/picomatch@3.0.2': {} - ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -982,9 +973,9 @@ snapshots: '@esbuild/win32-ia32': 0.24.2 '@esbuild/win32-x64': 0.24.2 - fdir@6.4.3(picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805)): + fdir@6.4.3(picomatch@4.0.2): optionalDependencies: - picomatch: 4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805) + picomatch: 4.0.2 foreground-child@3.3.0: dependencies: @@ -1054,7 +1045,7 @@ snapshots: picocolors@1.1.1: {} - picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805): {} + picomatch@4.0.2: {} pirates@4.0.6: {} @@ -1147,8 +1138,8 @@ snapshots: tinyglobby@0.2.10: dependencies: - fdir: 6.4.3(picomatch@4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805)) - picomatch: 4.0.2(patch_hash=be85d04d529134b97aa354ee0e29f701cbe12c24f6311e00d0bc4e33d7484805) + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 tr46@1.0.1: dependencies: @@ -1188,6 +1179,8 @@ snapshots: undici-types@6.20.0: {} + unmatch@1.0.1: {} + webidl-conversions@4.0.2: {} whatwg-url@7.1.0: diff --git a/src/index.ts b/src/index.ts index e6932f6..4bbcfa4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import path, { posix } from 'node:path'; import { type Options as FdirOptions, fdir } from 'fdir'; -import picomatch from 'picomatch'; +import match from 'unmatch'; import { escapePath, getPartialMatcher, isDynamicPattern, log, splitPattern } from './utils.ts'; const PARENT_DIRECTORY = /^(\/?\.\.)+/; @@ -184,16 +184,16 @@ function crawl(options: GlobOptions, cwd: string, sync: boolean) { log('internal processing patterns:', processed); } - const unignoreMatcher = processed.unignore.length === 0 ? undefined : picomatch(processed.unignore); + const unignoreMatcher = processed.unignore.length === 0 ? undefined : match(processed.unignore); - const matcher = picomatch(processed.match, { + const matcher = match(processed.match, { dot: options.dot, nocase, ignore: processed.ignore, - onIgnore: unignoreMatcher ? result => unignoreMatcher(result.output) : undefined + onIgnore: unignoreMatcher ? result => unignoreMatcher(result.output) && match.constants.UNIGNORE : undefined }); - const ignore = picomatch(processed.ignore, { + const ignore = match(processed.ignore, { dot: options.dot, nocase }); diff --git a/src/utils.ts b/src/utils.ts index 275789b..e3683b7 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import picomatch, { type Matcher } from 'picomatch'; +import match, { type Matcher } from 'unmatch'; // #region PARTIAL MATCHER export interface PartialMatcherOptions { @@ -18,7 +18,7 @@ export function getPartialMatcher(patterns: string[], options?: PartialMatcherOp const partsCount = parts.length; const partRegexes = Array(partsCount); for (let j = 0; j < partsCount; j++) { - partRegexes[j] = picomatch.makeRe(parts[j], options); + partRegexes[j] = match.makeRe(parts[j], options); } regexes[i] = partRegexes; } @@ -72,7 +72,7 @@ const splitPatternOptions = { parts: true }; // if a pattern has no slashes outside glob symbols, results.parts is [] export function splitPattern(path: string): string[] { - const result = picomatch.scan(path, splitPatternOptions); + const result = match.scan(path, splitPatternOptions); return result.parts?.length ? result.parts : [path]; } // #endregion @@ -129,7 +129,7 @@ export function isDynamicPattern(pattern: string, options?: { caseSensitiveMatch return true; } - const scan = picomatch.scan(pattern); + const scan = match.scan(pattern); return scan.isGlob || scan.negated; } // #endregion