From 2dccc39b9f390a374cc5ce1428b069e3fb47fe2e Mon Sep 17 00:00:00 2001 From: mrmlnc Date: Tue, 2 Jul 2024 12:25:55 +0300 Subject: [PATCH 1/2] build: fix watch command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 614f09e8..dfa095ac 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "test:e2e:stream": "mocha \"out/**/*.e2e.js\" -s 0 --grep \"\\(stream\\)\"", "_build:compile": "npm run clean && npm run compile", "build": "npm run _build:compile && npm run lint && npm test", - "watch": "npm run _build:compile -- --sourceMap --watch", + "watch": "npm run _build:compile -- -- --sourceMap --watch", "_bundle:dts": "tsc --emitDeclarationOnly --outDir ./build", "_bundle:ts": "esbuild --bundle ./src/index.ts --outfile=./build/index.js --platform=node --target=node16.14 --format=cjs", "_bundle:build": "npm run _bundle:dts && npm run _bundle:ts", From 4df40bd53cc3f71e075d97d013ab4945ca386985 Mon Sep 17 00:00:00 2001 From: mrmlnc Date: Tue, 2 Jul 2024 19:14:14 +0300 Subject: [PATCH 2/2] fix: apply absolute negative patterns to full path instead of file path --- __snapshots__/absolute.e2e.js | 12 ++++++ src/providers/filters/entry.ts | 55 +++++++++++++++++---------- src/tests/e2e/options/absolute.e2e.ts | 8 ++++ src/utils/pattern.spec.ts | 14 +++++++ src/utils/pattern.ts | 19 +++++++++ 5 files changed, 88 insertions(+), 20 deletions(-) diff --git a/__snapshots__/absolute.e2e.js b/__snapshots__/absolute.e2e.js index 55fe8303..bd140f5b 100644 --- a/__snapshots__/absolute.e2e.js +++ b/__snapshots__/absolute.e2e.js @@ -351,3 +351,15 @@ exports['Options Absolute (cwd & ignore) {"pattern":"**","options":{"ignore":["< exports['Options Absolute (cwd & ignore) {"pattern":"**","options":{"ignore":["/fixtures/**"],"cwd":"fixtures","absolute":true}} (async) 1'] = [] exports['Options Absolute (cwd & ignore) {"pattern":"**","options":{"ignore":["/fixtures/**"],"cwd":"fixtures","absolute":true}} (stream) 1'] = [] + +exports['Options Absolute (cwd & ignore) {"pattern":"file.md","options":{"ignore":["**/fixtures/**"],"cwd":"fixtures","absolute":true}} (sync) 1'] = [ + "/fixtures/file.md" +] + +exports['Options Absolute (cwd & ignore) {"pattern":"file.md","options":{"ignore":["**/fixtures/**"],"cwd":"fixtures","absolute":true}} (async) 1'] = [ + "/fixtures/file.md" +] + +exports['Options Absolute (cwd & ignore) {"pattern":"file.md","options":{"ignore":["**/fixtures/**"],"cwd":"fixtures","absolute":true}} (stream) 1'] = [ + "/fixtures/file.md" +] diff --git a/src/providers/filters/entry.ts b/src/providers/filters/entry.ts index 47ed8a91..d596e0d8 100644 --- a/src/providers/filters/entry.ts +++ b/src/providers/filters/entry.ts @@ -3,6 +3,16 @@ import * as utils from '../../utils'; import type Settings from '../../settings'; import type { MicromatchOptions, Entry, EntryFilterFunction, Pattern, PatternRe } from '../../types'; +interface PatternsRegexSet { + positive: { + all: PatternRe[]; + }; + negative: { + absolute: PatternRe[]; + relative: PatternRe[]; + }; +} + export default class EntryFilter { public readonly index = new Map(); @@ -15,16 +25,22 @@ export default class EntryFilter { } public getFilter(positive: Pattern[], negative: Pattern[]): EntryFilterFunction { - const positiveRe = utils.pattern.convertPatternsToRe(positive, this.#micromatchOptions); - const negativeRe = utils.pattern.convertPatternsToRe(negative, { - ...this.#micromatchOptions, - dot: true, - }); - - return (entry) => this.#filter(entry, positiveRe, negativeRe); + const [absoluteNegative, relativeNegative] = utils.pattern.partitionAbsoluteAndRelative(negative); + + const patterns: PatternsRegexSet = { + positive: { + all: utils.pattern.convertPatternsToRe(positive, this.#micromatchOptions), + }, + negative: { + absolute: utils.pattern.convertPatternsToRe(absoluteNegative, { ...this.#micromatchOptions, dot: true }), + relative: utils.pattern.convertPatternsToRe(relativeNegative, { ...this.#micromatchOptions, dot: true }), + }, + }; + + return (entry) => this.#filter(entry, patterns); } - #filter(entry: Entry, positiveRe: PatternRe[], negativeRe: PatternRe[]): boolean { + #filter(entry: Entry, pattens: PatternsRegexSet): boolean { const filepath = utils.path.removeLeadingDotSegment(entry.path); if (this.#settings.unique && this.#isDuplicateEntry(filepath)) { @@ -35,13 +51,7 @@ export default class EntryFilter { return false; } - if (this.#isSkippedByAbsoluteNegativePatterns(filepath, negativeRe)) { - return false; - } - - const isDirectory = entry.dirent.isDirectory(); - - const isMatched = this.#isMatchToPatterns(filepath, positiveRe, isDirectory) && !this.#isMatchToPatterns(filepath, negativeRe, isDirectory); + const isMatched = this.#isMatchToPatternsSet(filepath, pattens, entry.dirent.isDirectory()); if (this.#settings.unique && isMatched) { this.#createIndexRecord(filepath); @@ -66,14 +76,19 @@ export default class EntryFilter { return this.#settings.onlyDirectories && !entry.dirent.isDirectory(); } - #isSkippedByAbsoluteNegativePatterns(entryPath: string, patternsRe: PatternRe[]): boolean { - if (!this.#settings.absolute) { - return false; + #isMatchToPatternsSet(filepath: string, patterns: PatternsRegexSet, isDirectory: boolean): boolean { + let fullpath = filepath; + + if (patterns.negative.absolute.length > 0) { + fullpath = utils.path.makeAbsolute(this.#settings.cwd, filepath); } - const fullpath = utils.path.makeAbsolute(this.#settings.cwd, entryPath); + const isMatched = this.#isMatchToPatterns(filepath, patterns.positive.all, isDirectory); - return utils.pattern.matchAny(fullpath, patternsRe); + return isMatched && !( + this.#isMatchToPatterns(filepath, patterns.negative.relative, isDirectory) || + this.#isMatchToPatterns(fullpath, patterns.negative.absolute, isDirectory) + ); } #isMatchToPatterns(filepath: string, patternsRe: PatternRe[], isDirectory: boolean): boolean { diff --git a/src/tests/e2e/options/absolute.e2e.ts b/src/tests/e2e/options/absolute.e2e.ts index 2806ed5f..86b809b5 100644 --- a/src/tests/e2e/options/absolute.e2e.ts +++ b/src/tests/e2e/options/absolute.e2e.ts @@ -126,6 +126,14 @@ runner.suite('Options Absolute (cwd & ignore)', { absolute: true, }, }, + { + pattern: 'file.md', + options: { + ignore: [path.posix.join('**', 'fixtures', '**')], + cwd: 'fixtures', + absolute: true, + }, + }, { pattern: '*', diff --git a/src/utils/pattern.spec.ts b/src/utils/pattern.spec.ts index 97c2d802..beea2977 100644 --- a/src/utils/pattern.spec.ts +++ b/src/utils/pattern.spec.ts @@ -540,4 +540,18 @@ describe('Utils → Pattern', () => { assert.strictEqual(action('///?/D:/'), '//?/D:/'); }); }); + + describe('.isAbsolute', () => { + it('should return true', () => { + const actual = util.isAbsolute('/directory/file.txt'); + + assert.ok(actual); + }); + + it('should return false', () => { + const actual = util.isAbsolute('directory/file.txt'); + + assert.ok(!actual); + }); + }); }); diff --git a/src/utils/pattern.ts b/src/utils/pattern.ts index 00c69c40..8c4c5342 100644 --- a/src/utils/pattern.ts +++ b/src/utils/pattern.ts @@ -217,3 +217,22 @@ export function matchAny(entry: string, patternsRe: PatternRe[]): boolean { export function removeDuplicateSlashes(pattern: string): string { return pattern.replaceAll(DOUBLE_SLASH_RE, '/'); } + +export function partitionAbsoluteAndRelative(patterns: Pattern[]): [Pattern[], Pattern[]] { + const absolute: Pattern[] = []; + const relative: Pattern[] = []; + + for (const pattern of patterns) { + if (isAbsolute(pattern)) { + absolute.push(pattern); + } else { + relative.push(pattern); + } + } + + return [absolute, relative]; +} + +export function isAbsolute(pattern: string): boolean { + return path.isAbsolute(pattern); +}