summaryrefslogtreecommitdiff
path: root/std/fs/expand_glob.ts
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2020-04-29 22:00:31 +0200
committerGitHub <noreply@github.com>2020-04-29 16:00:31 -0400
commit3e6ea6284178df0be4982d9775f47b47b14c6139 (patch)
treeed684ea536e32023e72004110556ad8285126676 /std/fs/expand_glob.ts
parent721a4ad59d4a8bdd8470d6b98839137f14c84ba9 (diff)
BREAKING: Include limited metadata in 'DirEntry' objects (#4941)
This change is to prevent needed a separate stat syscall for each file when using readdir. For consistency, this PR also modifies std's `WalkEntry` interface to extend `DirEntry` with an additional `path` field.
Diffstat (limited to 'std/fs/expand_glob.ts')
-rw-r--r--std/fs/expand_glob.ts82
1 files changed, 42 insertions, 40 deletions
diff --git a/std/fs/expand_glob.ts b/std/fs/expand_glob.ts
index 386f61ad5..803c67cdf 100644
--- a/std/fs/expand_glob.ts
+++ b/std/fs/expand_glob.ts
@@ -8,9 +8,15 @@ import {
joinGlobs,
normalize,
} from "../path/mod.ts";
-import { WalkEntry, walk, walkSync } from "./walk.ts";
+import {
+ WalkEntry,
+ createWalkEntry,
+ createWalkEntrySync,
+ walk,
+ walkSync,
+} from "./walk.ts";
import { assert } from "../testing/asserts.ts";
-const { cwd, stat, statSync } = Deno;
+const { cwd } = Deno;
type FileInfo = Deno.FileInfo;
export interface ExpandGlobOptions extends GlobOptions {
@@ -48,6 +54,12 @@ function throwUnlessNotFound(error: Error): void {
}
}
+function comparePath(a: WalkEntry, b: WalkEntry): number {
+ if (a.path < b.path) return -1;
+ if (a.path > b.path) return 1;
+ return 0;
+}
+
/**
* Expand the glob string from the specified `root` directory and yield each
* result as a `WalkEntry` object.
@@ -73,8 +85,8 @@ export async function* expandGlob(
const excludePatterns = exclude
.map(resolveFromRoot)
.map((s: string): RegExp => globToRegExp(s, globOptions));
- const shouldInclude = (filename: string): boolean =>
- !excludePatterns.some((p: RegExp): boolean => !!filename.match(p));
+ const shouldInclude = (path: string): boolean =>
+ !excludePatterns.some((p: RegExp): boolean => !!path.match(p));
const { segments, hasTrailingSep, winRoot } = split(resolveFromRoot(glob));
let fixedRoot = winRoot != undefined ? winRoot : "/";
@@ -86,7 +98,7 @@ export async function* expandGlob(
let fixedRootInfo: WalkEntry;
try {
- fixedRootInfo = { filename: fixedRoot, info: await stat(fixedRoot) };
+ fixedRootInfo = await createWalkEntry(fixedRoot);
} catch (error) {
return throwUnlessNotFound(error);
}
@@ -95,29 +107,29 @@ export async function* expandGlob(
walkInfo: WalkEntry,
globSegment: string
): AsyncIterableIterator<WalkEntry> {
- if (!walkInfo.info.isDirectory) {
+ if (!walkInfo.isDirectory) {
return;
} else if (globSegment == "..") {
- const parentPath = joinGlobs([walkInfo.filename, ".."], globOptions);
+ const parentPath = joinGlobs([walkInfo.path, ".."], globOptions);
try {
if (shouldInclude(parentPath)) {
- return yield { filename: parentPath, info: await stat(parentPath) };
+ return yield await createWalkEntry(parentPath);
}
} catch (error) {
throwUnlessNotFound(error);
}
return;
} else if (globSegment == "**") {
- return yield* walk(walkInfo.filename, {
+ return yield* walk(walkInfo.path, {
includeFiles: false,
skip: excludePatterns,
});
}
- yield* walk(walkInfo.filename, {
+ yield* walk(walkInfo.path, {
maxDepth: 1,
match: [
globToRegExp(
- joinGlobs([walkInfo.filename, globSegment], globOptions),
+ joinGlobs([walkInfo.path, globSegment], globOptions),
globOptions
),
],
@@ -129,27 +141,22 @@ export async function* expandGlob(
for (const segment of segments) {
// Advancing the list of current matches may introduce duplicates, so we
// pass everything through this Map.
- const nextMatchMap: Map<string, FileInfo> = new Map();
+ const nextMatchMap: Map<string, WalkEntry> = new Map();
for (const currentMatch of currentMatches) {
for await (const nextMatch of advanceMatch(currentMatch, segment)) {
- nextMatchMap.set(nextMatch.filename, nextMatch.info);
+ nextMatchMap.set(nextMatch.path, nextMatch);
}
}
- currentMatches = [...nextMatchMap].sort().map(
- ([filename, info]): WalkEntry => ({
- filename,
- info,
- })
- );
+ currentMatches = [...nextMatchMap.values()].sort(comparePath);
}
if (hasTrailingSep) {
currentMatches = currentMatches.filter(
- ({ info }): boolean => info.isDirectory
+ (entry: WalkEntry): boolean => entry.isDirectory
);
}
if (!includeDirs) {
currentMatches = currentMatches.filter(
- ({ info }): boolean => !info.isDirectory
+ (entry: WalkEntry): boolean => !entry.isDirectory
);
}
yield* currentMatches;
@@ -177,8 +184,8 @@ export function* expandGlobSync(
const excludePatterns = exclude
.map(resolveFromRoot)
.map((s: string): RegExp => globToRegExp(s, globOptions));
- const shouldInclude = (filename: string): boolean =>
- !excludePatterns.some((p: RegExp): boolean => !!filename.match(p));
+ const shouldInclude = (path: string): boolean =>
+ !excludePatterns.some((p: RegExp): boolean => !!path.match(p));
const { segments, hasTrailingSep, winRoot } = split(resolveFromRoot(glob));
let fixedRoot = winRoot != undefined ? winRoot : "/";
@@ -190,7 +197,7 @@ export function* expandGlobSync(
let fixedRootInfo: WalkEntry;
try {
- fixedRootInfo = { filename: fixedRoot, info: statSync(fixedRoot) };
+ fixedRootInfo = createWalkEntrySync(fixedRoot);
} catch (error) {
return throwUnlessNotFound(error);
}
@@ -199,29 +206,29 @@ export function* expandGlobSync(
walkInfo: WalkEntry,
globSegment: string
): IterableIterator<WalkEntry> {
- if (!walkInfo.info.isDirectory) {
+ if (!walkInfo.isDirectory) {
return;
} else if (globSegment == "..") {
- const parentPath = joinGlobs([walkInfo.filename, ".."], globOptions);
+ const parentPath = joinGlobs([walkInfo.path, ".."], globOptions);
try {
if (shouldInclude(parentPath)) {
- return yield { filename: parentPath, info: statSync(parentPath) };
+ return yield createWalkEntrySync(parentPath);
}
} catch (error) {
throwUnlessNotFound(error);
}
return;
} else if (globSegment == "**") {
- return yield* walkSync(walkInfo.filename, {
+ return yield* walkSync(walkInfo.path, {
includeFiles: false,
skip: excludePatterns,
});
}
- yield* walkSync(walkInfo.filename, {
+ yield* walkSync(walkInfo.path, {
maxDepth: 1,
match: [
globToRegExp(
- joinGlobs([walkInfo.filename, globSegment], globOptions),
+ joinGlobs([walkInfo.path, globSegment], globOptions),
globOptions
),
],
@@ -233,27 +240,22 @@ export function* expandGlobSync(
for (const segment of segments) {
// Advancing the list of current matches may introduce duplicates, so we
// pass everything through this Map.
- const nextMatchMap: Map<string, FileInfo> = new Map();
+ const nextMatchMap: Map<string, WalkEntry> = new Map();
for (const currentMatch of currentMatches) {
for (const nextMatch of advanceMatch(currentMatch, segment)) {
- nextMatchMap.set(nextMatch.filename, nextMatch.info);
+ nextMatchMap.set(nextMatch.path, nextMatch);
}
}
- currentMatches = [...nextMatchMap].sort().map(
- ([filename, info]): WalkEntry => ({
- filename,
- info,
- })
- );
+ currentMatches = [...nextMatchMap.values()].sort(comparePath);
}
if (hasTrailingSep) {
currentMatches = currentMatches.filter(
- ({ info }): boolean => info.isDirectory
+ (entry: WalkEntry): boolean => entry.isDirectory
);
}
if (!includeDirs) {
currentMatches = currentMatches.filter(
- ({ info }): boolean => !info.isDirectory
+ (entry: WalkEntry): boolean => !entry.isDirectory
);
}
yield* currentMatches;