Skip to content

Commit 4db307a

Browse files
authored
fs: detect dot files when using globstar
Using globstar in glob pattern should not prevent dot (hidden) files from being matched. PR-URL: #61012 Fixes: #56321 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
1 parent a00d95c commit 4db307a

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

lib/internal/fs/glob.js

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,18 @@ class Glob {
442442
const fromSymlink = pattern.symlinks.has(index);
443443

444444
if (current === lazyMinimatch().GLOBSTAR) {
445-
if (entry.name[0] === '.' || (this.#exclude && this.#exclude(this.#withFileTypes ? entry : entry.name))) {
445+
const isDot = entry.name[0] === '.';
446+
const nextMatches = pattern.test(nextIndex, entry.name);
447+
448+
let nextNonGlobIndex = nextIndex;
449+
while (pattern.at(nextNonGlobIndex) === lazyMinimatch().GLOBSTAR) {
450+
nextNonGlobIndex++;
451+
}
452+
453+
const matchesDot = isDot && pattern.test(nextNonGlobIndex, entry.name);
454+
455+
if ((isDot && !matchesDot) ||
456+
(this.#exclude && this.#exclude(this.#withFileTypes ? entry : entry.name))) {
446457
continue;
447458
}
448459
if (!fromSymlink && entry.isDirectory()) {
@@ -455,7 +466,6 @@ class Glob {
455466

456467
// Any pattern after ** is also a potential pattern
457468
// so we can already test it here
458-
const nextMatches = pattern.test(nextIndex, entry.name);
459469
if (nextMatches && nextIndex === last && !isLast) {
460470
// If next pattern is the last one, add to results
461471
this.#results.add(entryPath);
@@ -642,30 +652,36 @@ class Glob {
642652
const fromSymlink = pattern.symlinks.has(index);
643653

644654
if (current === lazyMinimatch().GLOBSTAR) {
645-
if (entry.name[0] === '.' || (this.#exclude && this.#exclude(this.#withFileTypes ? entry : entry.name))) {
655+
const isDot = entry.name[0] === '.';
656+
const nextMatches = pattern.test(nextIndex, entry.name);
657+
658+
let nextNonGlobIndex = nextIndex;
659+
while (pattern.at(nextNonGlobIndex) === lazyMinimatch().GLOBSTAR) {
660+
nextNonGlobIndex++;
661+
}
662+
663+
const matchesDot = isDot && pattern.test(nextNonGlobIndex, entry.name);
664+
665+
if ((isDot && !matchesDot) ||
666+
(this.#exclude && this.#exclude(this.#withFileTypes ? entry : entry.name))) {
646667
continue;
647668
}
648669
if (!fromSymlink && entry.isDirectory()) {
649670
// If directory, add ** to its potential patterns
650671
subPatterns.add(index);
651672
} else if (!fromSymlink && index === last) {
652673
// If ** is last, add to results
653-
if (!this.#results.has(entryPath)) {
654-
if (this.#results.add(entryPath)) {
655-
yield this.#withFileTypes ? entry : entryPath;
656-
}
674+
if (!this.#results.has(entryPath) && this.#results.add(entryPath)) {
675+
yield this.#withFileTypes ? entry : entryPath;
657676
}
658677
}
659678

660679
// Any pattern after ** is also a potential pattern
661680
// so we can already test it here
662-
const nextMatches = pattern.test(nextIndex, entry.name);
663681
if (nextMatches && nextIndex === last && !isLast) {
664682
// If next pattern is the last one, add to results
665-
if (!this.#results.has(entryPath)) {
666-
if (this.#results.add(entryPath)) {
667-
yield this.#withFileTypes ? entry : entryPath;
668-
}
683+
if (!this.#results.has(entryPath) && this.#results.add(entryPath)) {
684+
yield this.#withFileTypes ? entry : entryPath;
669685
}
670686
} else if (nextMatches && entry.isDirectory()) {
671687
// Pattern matched, meaning two patterns forward

test/parallel/test-fs-glob.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ async function setup() {
3030
'a/cb/e/f',
3131
'a/x/.y/b',
3232
'a/z/.y/b',
33+
'a/.b',
34+
'a/b/.b',
3335
].map((f) => resolve(fixtureDir, f));
3436

3537
const symlinkTo = resolve(fixtureDir, 'a/symlink/a/b/c');
@@ -188,6 +190,9 @@ const patterns = {
188190
],
189191
'*/*/*/f': ['a/bc/e/f', 'a/cb/e/f'],
190192
'./**/f': ['a/bc/e/f', 'a/cb/e/f'],
193+
'**/.b': ['a/.b', 'a/b/.b'],
194+
'./**/.b': ['a/.b', 'a/b/.b'],
195+
'a/**/.b': ['a/.b', 'a/b/.b'],
191196
'a/symlink/a/b/c/a/b/c/a/b/c//a/b/c////a/b/c/**/b/c/**': common.isWindows ? [] : [
192197
'a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c',
193198
'a/symlink/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a/b/c/a',

0 commit comments

Comments
 (0)