mirror of
https://github.com/denoland/deno.git
synced 2024-11-29 16:30:56 -05:00
fix: Only swallow NotFound errors in std/fs/expandGlob() (#3479)
This commit is contained in:
parent
c93ae0b05a
commit
407195ea87
3 changed files with 52 additions and 23 deletions
|
@ -9,7 +9,9 @@ import {
|
||||||
normalize
|
normalize
|
||||||
} from "../path/mod.ts";
|
} from "../path/mod.ts";
|
||||||
import { WalkInfo, walk, walkSync } from "./walk.ts";
|
import { WalkInfo, walk, walkSync } from "./walk.ts";
|
||||||
const { cwd, stat, statSync } = Deno;
|
const { ErrorKind, cwd, stat, statSync } = Deno;
|
||||||
|
type ErrorKind = Deno.ErrorKind;
|
||||||
|
type DenoError = Deno.DenoError<ErrorKind>;
|
||||||
type FileInfo = Deno.FileInfo;
|
type FileInfo = Deno.FileInfo;
|
||||||
|
|
||||||
export interface ExpandGlobOptions extends GlobOptions {
|
export interface ExpandGlobOptions extends GlobOptions {
|
||||||
|
@ -41,13 +43,16 @@ function split(path: string): SplitPath {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function throwUnlessNotFound(error: Error): void {
|
||||||
|
if ((error as DenoError).kind != ErrorKind.NotFound) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand the glob string from the specified `root` directory and yield each
|
* Expand the glob string from the specified `root` directory and yield each
|
||||||
* result as a `WalkInfo` object.
|
* result as a `WalkInfo` object.
|
||||||
*/
|
*/
|
||||||
// TODO: Use a proper glob expansion algorithm.
|
|
||||||
// This is a very incomplete solution. The whole directory tree from `root` is
|
|
||||||
// walked and parent paths are not supported.
|
|
||||||
export async function* expandGlob(
|
export async function* expandGlob(
|
||||||
glob: string,
|
glob: string,
|
||||||
{
|
{
|
||||||
|
@ -69,7 +74,7 @@ export async function* expandGlob(
|
||||||
const excludePatterns = exclude
|
const excludePatterns = exclude
|
||||||
.map(resolveFromRoot)
|
.map(resolveFromRoot)
|
||||||
.map((s: string): RegExp => globToRegExp(s, globOptions));
|
.map((s: string): RegExp => globToRegExp(s, globOptions));
|
||||||
const shouldInclude = ({ filename }: WalkInfo): boolean =>
|
const shouldInclude = (filename: string): boolean =>
|
||||||
!excludePatterns.some((p: RegExp): boolean => !!filename.match(p));
|
!excludePatterns.some((p: RegExp): boolean => !!filename.match(p));
|
||||||
const { segments, hasTrailingSep, winRoot } = split(resolveFromRoot(glob));
|
const { segments, hasTrailingSep, winRoot } = split(resolveFromRoot(glob));
|
||||||
|
|
||||||
|
@ -81,8 +86,8 @@ export async function* expandGlob(
|
||||||
let fixedRootInfo: WalkInfo;
|
let fixedRootInfo: WalkInfo;
|
||||||
try {
|
try {
|
||||||
fixedRootInfo = { filename: fixedRoot, info: await stat(fixedRoot) };
|
fixedRootInfo = { filename: fixedRoot, info: await stat(fixedRoot) };
|
||||||
} catch {
|
} catch (error) {
|
||||||
return;
|
return throwUnlessNotFound(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function* advanceMatch(
|
async function* advanceMatch(
|
||||||
|
@ -94,12 +99,13 @@ export async function* expandGlob(
|
||||||
} else if (globSegment == "..") {
|
} else if (globSegment == "..") {
|
||||||
const parentPath = joinGlobs([walkInfo.filename, ".."], globOptions);
|
const parentPath = joinGlobs([walkInfo.filename, ".."], globOptions);
|
||||||
try {
|
try {
|
||||||
return yield* [
|
if (shouldInclude(parentPath)) {
|
||||||
{ filename: parentPath, info: await stat(parentPath) }
|
return yield { filename: parentPath, info: await stat(parentPath) };
|
||||||
].filter(shouldInclude);
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throwUnlessNotFound(error);
|
||||||
|
}
|
||||||
|
return;
|
||||||
} else if (globSegment == "**") {
|
} else if (globSegment == "**") {
|
||||||
return yield* walk(walkInfo.filename, {
|
return yield* walk(walkInfo.filename, {
|
||||||
includeFiles: false,
|
includeFiles: false,
|
||||||
|
@ -149,7 +155,6 @@ export async function* expandGlob(
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Synchronous version of `expandGlob()`. */
|
/** Synchronous version of `expandGlob()`. */
|
||||||
// TODO: As `expandGlob()`.
|
|
||||||
export function* expandGlobSync(
|
export function* expandGlobSync(
|
||||||
glob: string,
|
glob: string,
|
||||||
{
|
{
|
||||||
|
@ -171,7 +176,7 @@ export function* expandGlobSync(
|
||||||
const excludePatterns = exclude
|
const excludePatterns = exclude
|
||||||
.map(resolveFromRoot)
|
.map(resolveFromRoot)
|
||||||
.map((s: string): RegExp => globToRegExp(s, globOptions));
|
.map((s: string): RegExp => globToRegExp(s, globOptions));
|
||||||
const shouldInclude = ({ filename }: WalkInfo): boolean =>
|
const shouldInclude = (filename: string): boolean =>
|
||||||
!excludePatterns.some((p: RegExp): boolean => !!filename.match(p));
|
!excludePatterns.some((p: RegExp): boolean => !!filename.match(p));
|
||||||
const { segments, hasTrailingSep, winRoot } = split(resolveFromRoot(glob));
|
const { segments, hasTrailingSep, winRoot } = split(resolveFromRoot(glob));
|
||||||
|
|
||||||
|
@ -183,8 +188,8 @@ export function* expandGlobSync(
|
||||||
let fixedRootInfo: WalkInfo;
|
let fixedRootInfo: WalkInfo;
|
||||||
try {
|
try {
|
||||||
fixedRootInfo = { filename: fixedRoot, info: statSync(fixedRoot) };
|
fixedRootInfo = { filename: fixedRoot, info: statSync(fixedRoot) };
|
||||||
} catch {
|
} catch (error) {
|
||||||
return;
|
return throwUnlessNotFound(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* advanceMatch(
|
function* advanceMatch(
|
||||||
|
@ -196,12 +201,13 @@ export function* expandGlobSync(
|
||||||
} else if (globSegment == "..") {
|
} else if (globSegment == "..") {
|
||||||
const parentPath = joinGlobs([walkInfo.filename, ".."], globOptions);
|
const parentPath = joinGlobs([walkInfo.filename, ".."], globOptions);
|
||||||
try {
|
try {
|
||||||
return yield* [
|
if (shouldInclude(parentPath)) {
|
||||||
{ filename: parentPath, info: statSync(parentPath) }
|
return yield { filename: parentPath, info: statSync(parentPath) };
|
||||||
].filter(shouldInclude);
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throwUnlessNotFound(error);
|
||||||
|
}
|
||||||
|
return;
|
||||||
} else if (globSegment == "**") {
|
} else if (globSegment == "**") {
|
||||||
return yield* walkSync(walkInfo.filename, {
|
return yield* walkSync(walkInfo.filename, {
|
||||||
includeFiles: false,
|
includeFiles: false,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const { cwd } = Deno;
|
const { cwd, execPath, run } = Deno;
|
||||||
|
import { decode } from "../strings/mod.ts";
|
||||||
import { test, runIfMain } from "../testing/mod.ts";
|
import { test, runIfMain } from "../testing/mod.ts";
|
||||||
import { assert, assertEquals } from "../testing/asserts.ts";
|
import { assert, assertEquals, assertStrContains } from "../testing/asserts.ts";
|
||||||
import {
|
import {
|
||||||
isWindows,
|
isWindows,
|
||||||
join,
|
join,
|
||||||
|
@ -117,4 +118,20 @@ test(async function expandGlobIncludeDirs(): Promise<void> {
|
||||||
assertEquals(await expandGlobArray("subdir", options), []);
|
assertEquals(await expandGlobArray("subdir", options), []);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(async function expandGlobPermError(): Promise<void> {
|
||||||
|
const exampleUrl = new URL("testdata/expand_wildcard.js", import.meta.url);
|
||||||
|
const p = run({
|
||||||
|
args: [execPath(), exampleUrl.toString()],
|
||||||
|
stdin: "null",
|
||||||
|
stdout: "piped",
|
||||||
|
stderr: "piped"
|
||||||
|
});
|
||||||
|
assertEquals(await p.status(), { code: 1, success: false });
|
||||||
|
assertEquals(decode(await p.output()), "");
|
||||||
|
assertStrContains(
|
||||||
|
decode(await p.stderrOutput()),
|
||||||
|
"Uncaught PermissionDenied"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
runIfMain(import.meta);
|
runIfMain(import.meta);
|
||||||
|
|
6
std/fs/testdata/expand_wildcard.js
vendored
Normal file
6
std/fs/testdata/expand_wildcard.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { expandGlob } from "../expand_glob.ts";
|
||||||
|
|
||||||
|
const glob = new URL("*", import.meta.url).pathname;
|
||||||
|
for await (const { filename } of expandGlob(glob)) {
|
||||||
|
console.log(filename);
|
||||||
|
}
|
Loading…
Reference in a new issue