refactor(fs): improve expandGlob() implementation and testing (#5089)

This commit is contained in:
Yoshiya Hinosawa 2024-06-20 16:39:45 +09:00 committed by GitHub
parent f863a2b241
commit bd55f3b5c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 27 deletions

View File

@ -290,14 +290,9 @@ export async function* expandGlob(
const shouldInclude = (path: string): boolean =>
!excludePatterns.some((p: RegExp): boolean => !!path.match(p));
let fixedRoot = isGlobAbsolute
? winRoot !== undefined ? winRoot : "/"
: absRoot;
let fixedRoot = isGlobAbsolute ? winRoot ?? "/" : absRoot;
while (segments.length > 0 && !isGlob(segments[0]!)) {
const seg = segments.shift();
if (seg === undefined) {
throw new TypeError("Unexpected undefined segment");
}
const seg = segments.shift()!;
fixedRoot = joinGlobs([fixedRoot, seg], globOptions);
}
@ -316,12 +311,8 @@ export async function* expandGlob(
return;
} else if (globSegment === "..") {
const parentPath = joinGlobs([walkInfo.path, ".."], globOptions);
try {
if (shouldInclude(parentPath)) {
return yield await createWalkEntry(parentPath);
}
} catch (error) {
throwUnlessNotFound(error);
if (shouldInclude(parentPath)) {
return yield await createWalkEntry(parentPath);
}
return;
} else if (globSegment === "**") {
@ -454,14 +445,9 @@ export function* expandGlobSync(
const shouldInclude = (path: string): boolean =>
!excludePatterns.some((p: RegExp): boolean => !!path.match(p));
let fixedRoot = isGlobAbsolute
? winRoot !== undefined ? winRoot : "/"
: absRoot;
let fixedRoot = isGlobAbsolute ? winRoot ?? "/" : absRoot;
while (segments.length > 0 && !isGlob(segments[0]!)) {
const seg = segments.shift();
if (seg === undefined) {
throw new TypeError("Unexpected undefined segment");
}
const seg = segments.shift()!;
fixedRoot = joinGlobs([fixedRoot, seg], globOptions);
}
@ -480,12 +466,8 @@ export function* expandGlobSync(
return;
} else if (globSegment === "..") {
const parentPath = joinGlobs([walkInfo.path, ".."], globOptions);
try {
if (shouldInclude(parentPath)) {
return yield createWalkEntrySync(parentPath);
}
} catch (error) {
throwUnlessNotFound(error);
if (shouldInclude(parentPath)) {
return yield createWalkEntrySync(parentPath);
}
return;
} else if (globSegment === "**") {

View File

@ -1,5 +1,12 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assert, assertEquals, assertStringIncludes } from "@std/assert";
import {
assert,
assertEquals,
assertMatch,
assertRejects,
assertStringIncludes,
assertThrows,
} from "@std/assert";
import { fromFileUrl, join, joinGlobs, normalize, relative } from "@std/path";
import {
expandGlob,
@ -78,6 +85,55 @@ Deno.test("expandGlobSync() with wildcard input returns all test data", function
]);
});
Deno.test("expandGlob() excludes items in `exclude` option", async function () {
const options = { ...EG_OPTIONS, exclude: ["abc"] };
assertEquals(await expandGlobArray("*", options), [
"a[b]c",
"abcdef",
"abcdefghi",
"link",
"subdir",
]);
assertEquals(expandGlobSyncArray("*", options), [
"a[b]c",
"abcdef",
"abcdefghi",
"link",
"subdir",
]);
});
Deno.test("expandGlob() returns empty array if path doesn't exist", async function () {
assertEquals(await expandGlobArray("nonexistent", EG_OPTIONS), []);
assertEquals(expandGlobSyncArray("nonexistent", EG_OPTIONS), []);
});
Deno.test(
"expandGlob() throws permission error if the runtime doesn't have read permission",
{ permissions: {} },
async function () {
{
const e = await assertRejects(async () => {
await expandGlobArray("*", EG_OPTIONS);
}, Deno.errors.PermissionDenied);
assertMatch(
e.message,
/^Requires read access to "[^"]+", run again with the --allow-read flag$/,
);
}
{
const e = assertThrows(() => {
expandGlobSyncArray("*", EG_OPTIONS);
}, Deno.errors.PermissionDenied);
assertMatch(
e.message,
/^Requires read access to "[^"]+", run again with the --allow-read flag$/,
);
}
},
);
Deno.test("expandGlob() with */ input returns subdirs", async function () {
const options = EG_OPTIONS;
assertEquals(await expandGlobArray("*/", options), [