mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
fs: apply exclude function to root path
In at least some situations, the root path was being added to the results of globbing even if it matched the optional exclude function. In the relevant test file, a variable was renamed for consistency. (There was a patterns and pattern2, rather than patterns2.) The test case is added to patterns2. Fixes: https://github.com/nodejs/node/issues/56260 PR-URL: https://github.com/nodejs/node/pull/57420 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Jason Zhang <xzha4350@gmail.com> Reviewed-By: LiviaMedeiros <livia@cirno.name> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ const {
|
||||
ArrayPrototypePop,
|
||||
ArrayPrototypePush,
|
||||
ArrayPrototypeSome,
|
||||
Promise,
|
||||
PromisePrototypeThen,
|
||||
SafeMap,
|
||||
SafeSet,
|
||||
@@ -125,7 +126,8 @@ class Cache {
|
||||
}
|
||||
statSync(path) {
|
||||
const cached = this.#statsCache.get(path);
|
||||
if (cached) {
|
||||
// Do not return a promise from a sync function.
|
||||
if (cached && !(cached instanceof Promise)) {
|
||||
return cached;
|
||||
}
|
||||
const val = getDirentSync(path);
|
||||
@@ -326,6 +328,28 @@ class Glob {
|
||||
if (this.#isExcluded(path)) {
|
||||
return;
|
||||
}
|
||||
const fullpath = resolve(this.#root, path);
|
||||
|
||||
// If path is a directory, add trailing slash and test patterns again.
|
||||
// TODO(Trott): Would running #isExcluded() first and checking isDirectory() only
|
||||
// if it matches be more performant in the typical use case? #isExcluded()
|
||||
// is often ()=>false which is about as optimizable as a function gets.
|
||||
if (this.#cache.statSync(fullpath).isDirectory() && this.#isExcluded(`${fullpath}/`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.#exclude) {
|
||||
if (this.#withFileTypes) {
|
||||
const stat = this.#cache.statSync(path);
|
||||
if (stat !== null) {
|
||||
if (this.#exclude(stat)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (this.#exclude(path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!this.#subpatterns.has(path)) {
|
||||
this.#subpatterns.set(path, [pattern]);
|
||||
} else {
|
||||
|
||||
@@ -388,7 +388,7 @@ describe('fsPromises glob - withFileTypes', function() {
|
||||
});
|
||||
|
||||
// [pattern, exclude option, expected result]
|
||||
const pattern2 = [
|
||||
const patterns2 = [
|
||||
['a/{b,c}*', ['a/*c'], ['a/b', 'a/cb']],
|
||||
['a/{a,b,c}*', ['a/*bc*', 'a/cb'], ['a/b', 'a/c']],
|
||||
['a/**/[cg]', ['**/c'], ['a/abcdef/g', 'a/abcfed/g']],
|
||||
@@ -427,6 +427,10 @@ const pattern2 = [
|
||||
[`${absDir}/*{a,q}*`, './a/*{c,b}*/*'],
|
||||
[`${absDir}/foo`, 'a/c', ...(common.isWindows ? [] : ['a/symlink/a/b/c'])],
|
||||
],
|
||||
[ 'a/**', () => true, [] ],
|
||||
[ 'a/**', [ '*' ], [] ],
|
||||
[ 'a/**', [ '**' ], [] ],
|
||||
[ 'a/**', [ 'a/**' ], [] ],
|
||||
];
|
||||
|
||||
describe('globSync - exclude', function() {
|
||||
@@ -436,7 +440,7 @@ describe('globSync - exclude', function() {
|
||||
assert.strictEqual(actual.length, 0);
|
||||
});
|
||||
}
|
||||
for (const [pattern, exclude, expected] of pattern2) {
|
||||
for (const [pattern, exclude, expected] of patterns2) {
|
||||
test(`${pattern} - exclude: ${exclude}`, () => {
|
||||
const actual = globSync(pattern, { cwd: fixtureDir, exclude }).sort();
|
||||
const normalized = expected.filter(Boolean).map((item) => item.replaceAll('/', sep)).sort();
|
||||
@@ -453,7 +457,7 @@ describe('glob - exclude', function() {
|
||||
assert.strictEqual(actual.length, 0);
|
||||
});
|
||||
}
|
||||
for (const [pattern, exclude, expected] of pattern2) {
|
||||
for (const [pattern, exclude, expected] of patterns2) {
|
||||
test(`${pattern} - exclude: ${exclude}`, async () => {
|
||||
const actual = (await promisified(pattern, { cwd: fixtureDir, exclude })).sort();
|
||||
const normalized = expected.filter(Boolean).map((item) => item.replaceAll('/', sep)).sort();
|
||||
@@ -471,7 +475,7 @@ describe('fsPromises glob - exclude', function() {
|
||||
assert.strictEqual(actual.length, 0);
|
||||
});
|
||||
}
|
||||
for (const [pattern, exclude, expected] of pattern2) {
|
||||
for (const [pattern, exclude, expected] of patterns2) {
|
||||
test(`${pattern} - exclude: ${exclude}`, async () => {
|
||||
const actual = [];
|
||||
for await (const item of asyncGlob(pattern, { cwd: fixtureDir, exclude })) actual.push(item);
|
||||
|
||||
Reference in New Issue
Block a user