fs: allow 'withFileTypes' to be used with globs · nodejs/node@7d7a762 · GitHub
Skip to content

Commit 7d7a762

Browse files
avivkellertargos
authored andcommitted
fs: allow 'withFileTypes' to be used with globs
PR-URL: #52837 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
1 parent 0bbc62c commit 7d7a762

4 files changed

Lines changed: 92 additions & 16 deletions

File tree

doc/api/fs.md

Lines changed: 18 additions & 0 deletions

lib/internal/fs/glob.js

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const {
1616

1717
const { lstatSync, readdirSync } = require('fs');
1818
const { lstat, readdir } = require('fs/promises');
19-
const { join, resolve } = require('path');
19+
const { join, resolve, basename, isAbsolute } = require('path');
2020

2121
const {
2222
kEmptyObject,
@@ -27,6 +27,7 @@ const {
2727
validateString,
2828
validateStringArray,
2929
} = require('internal/validators');
30+
const { DirentFromStats } = require('internal/fs/utils');
3031

3132
let minimatch;
3233
function lazyMinimatch() {
@@ -37,6 +38,14 @@ function lazyMinimatch() {
3738
const isWindows = process.platform === 'win32';
3839
const isOSX = process.platform === 'darwin';
3940

41+
async function getDirent(path) {
42+
return new DirentFromStats(basename(path), await lstat(path), path);
43+
}
44+
45+
function getDirentSync(path) {
46+
return new DirentFromStats(basename(path), lstatSync(path), path);
47+
}
48+
4049
class Cache {
4150
#cache = new SafeMap();
4251
#statsCache = new SafeMap();
@@ -47,7 +56,7 @@ class Cache {
4756
if (cached) {
4857
return cached;
4958
}
50-
const promise = PromisePrototypeThen(lstat(path), null, () => null);
59+
const promise = PromisePrototypeThen(getDirent(path), null, () => null);
5160
this.#statsCache.set(path, promise);
5261
return promise;
5362
}
@@ -58,7 +67,7 @@ class Cache {
5867
}
5968
let val;
6069
try {
61-
val = lstatSync(path);
70+
val = getDirentSync(path);
6271
} catch {
6372
val = null;
6473
}
@@ -175,14 +184,16 @@ class Glob {
175184
#queue = [];
176185
#subpatterns = new SafeMap();
177186
#patterns;
187+
#withFileTypes;
178188
constructor(pattern, options = kEmptyObject) {
179189
validateObject(options, 'options');
180-
const { exclude, cwd } = options;
190+
const { exclude, cwd, withFileTypes } = options;
181191
if (exclude != null) {
182192
validateFunction(exclude, 'options.exclude');
183193
}
184194
this.#root = cwd ?? '.';
185195
this.#exclude = exclude;
196+
this.#withFileTypes = !!withFileTypes;
186197
let patterns;
187198
if (typeof pattern === 'object') {
188199
validateStringArray(pattern, 'patterns');
@@ -222,7 +233,14 @@ class Glob {
222233
.forEach((patterns, path) => ArrayPrototypePush(this.#queue, { __proto__: null, path, patterns }));
223234
this.#subpatterns.clear();
224235
}
225-
return ArrayFrom(this.#results);
236+
return ArrayFrom(
237+
this.#results,
238+
this.#withFileTypes ? (path) => this.#cache.statSync(
239+
isAbsolute(path) ?
240+
path :
241+
join(this.#root, path),
242+
) : undefined,
243+
);
226244
}
227245
#addSubpattern(path, pattern) {
228246
if (!this.#subpatterns.has(path)) {
@@ -317,7 +335,7 @@ class Glob {
317335
const fromSymlink = pattern.symlinks.has(index);
318336

319337
if (current === lazyMinimatch().GLOBSTAR) {
320-
if (entry.name[0] === '.' || (this.#exclude && this.#exclude(entry.name))) {
338+
if (entry.name[0] === '.' || (this.#exclude && this.#exclude(this.#withFileTypes ? entry : entry.name))) {
321339
continue;
322340
}
323341
if (!fromSymlink && entry.isDirectory()) {
@@ -460,7 +478,7 @@ class Glob {
460478
const result = join(path, p);
461479
if (!this.#results.has(result)) {
462480
this.#results.add(result);
463-
yield result;
481+
yield this.#withFileTypes ? stat : result;
464482
}
465483
}
466484
if (pattern.indexes.size === 1 && pattern.indexes.has(last)) {
@@ -472,7 +490,7 @@ class Glob {
472490
// if path is ".", add it only if pattern starts with "." or pattern is exactly "**"
473491
if (!this.#results.has(path)) {
474492
this.#results.add(path);
475-
yield path;
493+
yield this.#withFileTypes ? stat : path;
476494
}
477495
}
478496

@@ -522,7 +540,7 @@ class Glob {
522540
// If ** is last, add to results
523541
if (!this.#results.has(entryPath)) {
524542
this.#results.add(entryPath);
525-
yield entryPath;
543+
yield this.#withFileTypes ? entry : entryPath;
526544
}
527545
}
528546

@@ -533,7 +551,7 @@ class Glob {
533551
// If next pattern is the last one, add to results
534552
if (!this.#results.has(entryPath)) {
535553
this.#results.add(entryPath);
536-
yield entryPath;
554+
yield this.#withFileTypes ? entry : entryPath;
537555
}
538556
} else if (nextMatches && entry.isDirectory()) {
539557
// Pattern mached, meaning two patterns forward
@@ -569,14 +587,14 @@ class Glob {
569587
this.#cache.add(path, pattern.child(new SafeSet().add(nextIndex)));
570588
if (!this.#results.has(path)) {
571589
this.#results.add(path);
572-
yield path;
590+
yield this.#withFileTypes ? this.#cache.statSync(fullpath) : path;
573591
}
574592
}
575593
if (!this.#cache.seen(path, pattern, nextIndex) || !this.#cache.seen(parent, pattern, nextIndex)) {
576594
this.#cache.add(parent, pattern.child(new SafeSet().add(nextIndex)));
577595
if (!this.#results.has(parent)) {
578596
this.#results.add(parent);
579-
yield parent;
597+
yield this.#withFileTypes ? this.#cache.statSync(join(this.#root, parent)) : parent;
580598
}
581599
}
582600
}
@@ -592,7 +610,7 @@ class Glob {
592610
if (nextIndex === last) {
593611
if (!this.#results.has(entryPath)) {
594612
this.#results.add(entryPath);
595-
yield entryPath;
613+
yield this.#withFileTypes ? entry : entryPath;
596614
}
597615
} else {
598616
subPatterns.add(nextIndex + 1);
@@ -605,7 +623,7 @@ class Glob {
605623
if (index === last) {
606624
if (!this.#results.has(entryPath)) {
607625
this.#results.add(entryPath);
608-
yield entryPath;
626+
yield this.#withFileTypes ? entry : entryPath;
609627
}
610628
} else if (entry.isDirectory()) {
611629
subPatterns.add(nextIndex);

lib/internal/fs/utils.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ module.exports = {
961961
BigIntStats, // for testing
962962
copyObject,
963963
Dirent,
964+
DirentFromStats,
964965
emitRecursiveRmdirWarning,
965966
getDirent,
966967
getDirents,

test/parallel/test-fs-glob.mjs

Lines changed: 41 additions & 2 deletions

0 commit comments

Comments
 (0)