Skip to content

Commit 73be367

Browse files
authored
Merge pull request #464 from mrmlnc/3.3.3
3.3.3
2 parents e60a9f5 + 55c7b33 commit 73be367

File tree

8 files changed

+112
-24
lines changed

8 files changed

+112
-24
lines changed

.eslintrc.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
"extends": "mrmlnc",
33
"rules": {
44
"no-magic-numbers": "off",
5-
"@typescript-eslint/no-magic-numbers": "off"
5+
"@typescript-eslint/no-magic-numbers": "off",
6+
"import/namespace": "off",
7+
"import/no-deprecated": "off"
68
},
79
"overrides": [
810
{

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ Indicates whether to traverse descendants of symbolic link directories when expa
394394
* Type: `FileSystemAdapter`
395395
* Default: `fs.*`
396396

397-
Custom implementation of methods for working with the file system.
397+
Custom implementation of methods for working with the file system. Supports objects with enumerable properties only.
398398

399399
```ts
400400
export interface FileSystemAdapter {

__snapshots__/absolute.e2e.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,15 @@ exports['Options Absolute (cwd & ignore) {"pattern":"**","options":{"ignore":["<
351351
exports['Options Absolute (cwd & ignore) {"pattern":"**","options":{"ignore":["<root>/fixtures/**"],"cwd":"fixtures","absolute":true}} (async) 1'] = []
352352

353353
exports['Options Absolute (cwd & ignore) {"pattern":"**","options":{"ignore":["<root>/fixtures/**"],"cwd":"fixtures","absolute":true}} (stream) 1'] = []
354+
355+
exports['Options Absolute (cwd & ignore) {"pattern":"file.md","options":{"ignore":["**/fixtures/**"],"cwd":"fixtures","absolute":true}} (sync) 1'] = [
356+
"<root>/fixtures/file.md"
357+
]
358+
359+
exports['Options Absolute (cwd & ignore) {"pattern":"file.md","options":{"ignore":["**/fixtures/**"],"cwd":"fixtures","absolute":true}} (async) 1'] = [
360+
"<root>/fixtures/file.md"
361+
]
362+
363+
exports['Options Absolute (cwd & ignore) {"pattern":"file.md","options":{"ignore":["**/fixtures/**"],"cwd":"fixtures","absolute":true}} (stream) 1'] = [
364+
"<root>/fixtures/file.md"
365+
]

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"eslint-config-mrmlnc": "^1.1.0",
4040
"execa": "^7.1.1",
4141
"fast-glob": "^3.0.4",
42-
"fdir": "^6.0.1",
42+
"fdir": "6.0.1",
4343
"glob": "^10.0.0",
4444
"hereby": "^1.8.1",
4545
"mocha": "^6.2.1",
@@ -53,7 +53,7 @@
5353
"@nodelib/fs.walk": "^1.2.3",
5454
"glob-parent": "^5.1.2",
5555
"merge2": "^1.3.0",
56-
"micromatch": "^4.0.4"
56+
"micromatch": "^4.0.8"
5757
},
5858
"scripts": {
5959
"clean": "rimraf out",
@@ -65,7 +65,7 @@
6565
"test:e2e:async": "mocha \"out/**/*.e2e.js\" -s 0 --grep \"\\(async\\)\"",
6666
"test:e2e:stream": "mocha \"out/**/*.e2e.js\" -s 0 --grep \"\\(stream\\)\"",
6767
"build": "npm run clean && npm run compile && npm run lint && npm test",
68-
"watch": "npm run clean && npm run compile -- --sourceMap --watch",
68+
"watch": "npm run clean && npm run compile -- -- --sourceMap --watch",
6969
"bench:async": "npm run bench:product:async && npm run bench:regression:async",
7070
"bench:stream": "npm run bench:product:stream && npm run bench:regression:stream",
7171
"bench:sync": "npm run bench:product:sync && npm run bench:regression:sync",

src/providers/filters/entry.ts

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,38 @@ import Settings from '../../settings';
22
import { Entry, EntryFilterFunction, MicromatchOptions, Pattern, PatternRe } from '../../types';
33
import * as utils from '../../utils';
44

5+
type PatternsRegexSet = {
6+
positive: {
7+
all: PatternRe[];
8+
};
9+
negative: {
10+
absolute: PatternRe[];
11+
relative: PatternRe[];
12+
};
13+
};
14+
515
export default class EntryFilter {
616
public readonly index: Map<string, undefined> = new Map();
717

818
constructor(private readonly _settings: Settings, private readonly _micromatchOptions: MicromatchOptions) {}
919

1020
public getFilter(positive: Pattern[], negative: Pattern[]): EntryFilterFunction {
11-
const positiveRe = utils.pattern.convertPatternsToRe(positive, this._micromatchOptions);
12-
const negativeRe = utils.pattern.convertPatternsToRe(negative, {
13-
...this._micromatchOptions,
14-
dot: true
15-
});
16-
17-
return (entry) => this._filter(entry, positiveRe, negativeRe);
21+
const [absoluteNegative, relativeNegative] = utils.pattern.partitionAbsoluteAndRelative(negative);
22+
23+
const patterns: PatternsRegexSet = {
24+
positive: {
25+
all: utils.pattern.convertPatternsToRe(positive, this._micromatchOptions)
26+
},
27+
negative: {
28+
absolute: utils.pattern.convertPatternsToRe(absoluteNegative, { ...this._micromatchOptions, dot: true }),
29+
relative: utils.pattern.convertPatternsToRe(relativeNegative, { ...this._micromatchOptions, dot: true })
30+
}
31+
};
32+
33+
return (entry) => this._filter(entry, patterns);
1834
}
1935

20-
private _filter(entry: Entry, positiveRe: PatternRe[], negativeRe: PatternRe[]): boolean {
36+
private _filter(entry: Entry, patterns: PatternsRegexSet): boolean {
2137
const filepath = utils.path.removeLeadingDotSegment(entry.path);
2238

2339
if (this._settings.unique && this._isDuplicateEntry(filepath)) {
@@ -28,13 +44,7 @@ export default class EntryFilter {
2844
return false;
2945
}
3046

31-
if (this._isSkippedByAbsoluteNegativePatterns(filepath, negativeRe)) {
32-
return false;
33-
}
34-
35-
const isDirectory = entry.dirent.isDirectory();
36-
37-
const isMatched = this._isMatchToPatterns(filepath, positiveRe, isDirectory) && !this._isMatchToPatterns(filepath, negativeRe, isDirectory);
47+
const isMatched = this._isMatchToPatternsSet(filepath, patterns, entry.dirent.isDirectory());
3848

3949
if (this._settings.unique && isMatched) {
4050
this._createIndexRecord(filepath);
@@ -59,17 +69,40 @@ export default class EntryFilter {
5969
return this._settings.onlyDirectories && !entry.dirent.isDirectory();
6070
}
6171

62-
private _isSkippedByAbsoluteNegativePatterns(entryPath: string, patternsRe: PatternRe[]): boolean {
63-
if (!this._settings.absolute) {
72+
private _isMatchToPatternsSet(filepath: string, patterns: PatternsRegexSet, isDirectory: boolean): boolean {
73+
const isMatched = this._isMatchToPatterns(filepath, patterns.positive.all, isDirectory);
74+
if (!isMatched) {
75+
return false;
76+
}
77+
78+
const isMatchedByRelativeNegative = this._isMatchToPatterns(filepath, patterns.negative.relative, isDirectory);
79+
if (isMatchedByRelativeNegative) {
80+
return false;
81+
}
82+
83+
const isMatchedByAbsoluteNegative = this._isMatchToAbsoluteNegative(filepath, patterns.negative.absolute, isDirectory);
84+
if (isMatchedByAbsoluteNegative) {
85+
return false;
86+
}
87+
88+
return true;
89+
}
90+
91+
private _isMatchToAbsoluteNegative(filepath: string, patternsRe: PatternRe[], isDirectory: boolean): boolean {
92+
if (patternsRe.length === 0) {
6493
return false;
6594
}
6695

67-
const fullpath = utils.path.makeAbsolute(this._settings.cwd, entryPath);
96+
const fullpath = utils.path.makeAbsolute(this._settings.cwd, filepath);
6897

69-
return utils.pattern.matchAny(fullpath, patternsRe);
98+
return this._isMatchToPatterns(fullpath, patternsRe, isDirectory);
7099
}
71100

72101
private _isMatchToPatterns(filepath: string, patternsRe: PatternRe[], isDirectory: boolean): boolean {
102+
if (patternsRe.length === 0) {
103+
return false;
104+
}
105+
73106
// Trying to match files and directories by patterns.
74107
const isMatched = utils.pattern.matchAny(filepath, patternsRe);
75108

src/tests/e2e/options/absolute.e2e.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ runner.suite('Options Absolute (cwd & ignore)', {
121121
absolute: true
122122
}
123123
},
124+
{
125+
pattern: 'file.md',
126+
options: {
127+
ignore: [path.posix.join('**', 'fixtures', '**')],
128+
cwd: 'fixtures',
129+
absolute: true
130+
}
131+
},
124132

125133
{
126134
pattern: '*',

src/utils/pattern.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,4 +539,18 @@ describe('Utils → Pattern', () => {
539539
assert.strictEqual(action('///?/D:/'), '//?/D:/');
540540
});
541541
});
542+
543+
describe('.isAbsolute', () => {
544+
it('should return true', () => {
545+
const actual = util.isAbsolute('/directory/file.txt');
546+
547+
assert.ok(actual);
548+
});
549+
550+
it('should return false', () => {
551+
const actual = util.isAbsolute('directory/file.txt');
552+
553+
assert.ok(!actual);
554+
});
555+
});
542556
});

src/utils/pattern.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,22 @@ export function matchAny(entry: string, patternsRe: PatternRe[]): boolean {
215215
export function removeDuplicateSlashes(pattern: string): string {
216216
return pattern.replace(DOUBLE_SLASH_RE, '/');
217217
}
218+
219+
export function partitionAbsoluteAndRelative(patterns: Pattern[]): Pattern[][] {
220+
const absolute: Pattern[] = [];
221+
const relative: Pattern[] = [];
222+
223+
for (const pattern of patterns) {
224+
if (isAbsolute(pattern)) {
225+
absolute.push(pattern);
226+
} else {
227+
relative.push(pattern);
228+
}
229+
}
230+
231+
return [absolute, relative];
232+
}
233+
234+
export function isAbsolute(pattern: string): boolean {
235+
return path.isAbsolute(pattern);
236+
}

0 commit comments

Comments
 (0)