mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
BREAKING(fs): throw Deno.errors.NotFound
instead of WalkError
in walk[Sync]()
(#5477)
This commit is contained in:
parent
e689f43eee
commit
0dc7ce1a1c
128
fs/walk.ts
128
fs/walk.ts
@ -3,7 +3,6 @@
|
||||
// https://golang.org/pkg/path/filepath/#Walk
|
||||
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
||||
import { join } from "@std/path/join";
|
||||
import { normalize } from "@std/path/normalize";
|
||||
import { toPathString } from "./_to_path_string.ts";
|
||||
import {
|
||||
createWalkEntry,
|
||||
@ -11,56 +10,6 @@ import {
|
||||
type WalkEntry,
|
||||
} from "./_create_walk_entry.ts";
|
||||
|
||||
/**
|
||||
* Error thrown in {@linkcode walk} or {@linkcode walkSync} during iteration.
|
||||
*
|
||||
* @example Usage
|
||||
* ```ts no-eval
|
||||
* import { walk, WalkError } from "@std/fs/walk";
|
||||
*
|
||||
* try {
|
||||
* for await (const entry of walk("./non_existent_root")) {
|
||||
* console.log(entry.path);
|
||||
* }
|
||||
* } catch (error) {
|
||||
* if (error instanceof WalkError) {
|
||||
* console.error(error.message);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export class WalkError extends Error {
|
||||
/**
|
||||
* File path of the root that's being walked.
|
||||
*
|
||||
* @example Usage
|
||||
* ```ts
|
||||
* import { WalkError } from "@std/fs/walk";
|
||||
* import { assertEquals } from "@std/assert";
|
||||
*
|
||||
* const error = new WalkError("error message", "./foo");
|
||||
*
|
||||
* assertEquals(error.root, "./foo");
|
||||
* ```
|
||||
*/
|
||||
root: string;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param cause The cause of the error.
|
||||
* @param root The root directory that's being walked.
|
||||
*/
|
||||
constructor(cause: unknown, root: string) {
|
||||
super(
|
||||
`${cause instanceof Error ? cause.message : cause} for path "${root}"`,
|
||||
);
|
||||
this.cause = cause;
|
||||
this.name = this.constructor.name;
|
||||
this.root = root;
|
||||
}
|
||||
}
|
||||
|
||||
function include(
|
||||
path: string,
|
||||
exts?: string[],
|
||||
@ -79,11 +28,6 @@ function include(
|
||||
return true;
|
||||
}
|
||||
|
||||
function wrapErrorWithPath(err: unknown, root: string) {
|
||||
if (err instanceof WalkError) return err;
|
||||
return new WalkError(err, root);
|
||||
}
|
||||
|
||||
/** Options for {@linkcode walk} and {@linkcode walkSync}. */
|
||||
export interface WalkOptions {
|
||||
/**
|
||||
@ -163,6 +107,7 @@ export type { WalkEntry };
|
||||
*
|
||||
* @param root The root directory to start the walk from, as a string or URL.
|
||||
* @param options The options for the walk.
|
||||
* @throws {Deno.errors.NotFound} If the root directory does not exist.
|
||||
*
|
||||
* @returns An async iterable iterator that yields the walk entry objects.
|
||||
*
|
||||
@ -532,46 +477,42 @@ export async function* walk(
|
||||
if (maxDepth < 1 || !include(root, undefined, undefined, skip)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for await (const entry of Deno.readDir(root)) {
|
||||
let path = join(root, entry.name);
|
||||
for await (const entry of Deno.readDir(root)) {
|
||||
let path = join(root, entry.name);
|
||||
|
||||
let { isSymlink, isDirectory } = entry;
|
||||
let { isSymlink, isDirectory } = entry;
|
||||
|
||||
if (isSymlink) {
|
||||
if (!followSymlinks) {
|
||||
if (includeSymlinks && include(path, exts, match, skip)) {
|
||||
yield { path, ...entry };
|
||||
}
|
||||
continue;
|
||||
if (isSymlink) {
|
||||
if (!followSymlinks) {
|
||||
if (includeSymlinks && include(path, exts, match, skip)) {
|
||||
yield { path, ...entry };
|
||||
}
|
||||
const realPath = await Deno.realPath(path);
|
||||
if (canonicalize) {
|
||||
path = realPath;
|
||||
}
|
||||
// Caveat emptor: don't assume |path| is not a symlink. realpath()
|
||||
// resolves symlinks but another process can replace the file system
|
||||
// entity with a different type of entity before we call lstat().
|
||||
({ isSymlink, isDirectory } = await Deno.lstat(realPath));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isSymlink || isDirectory) {
|
||||
yield* walk(path, {
|
||||
maxDepth: maxDepth - 1,
|
||||
includeFiles,
|
||||
includeDirs,
|
||||
includeSymlinks,
|
||||
followSymlinks,
|
||||
exts,
|
||||
match,
|
||||
skip,
|
||||
});
|
||||
} else if (includeFiles && include(path, exts, match, skip)) {
|
||||
yield { path, ...entry };
|
||||
const realPath = await Deno.realPath(path);
|
||||
if (canonicalize) {
|
||||
path = realPath;
|
||||
}
|
||||
// Caveat emptor: don't assume |path| is not a symlink. realpath()
|
||||
// resolves symlinks but another process can replace the file system
|
||||
// entity with a different type of entity before we call lstat().
|
||||
({ isSymlink, isDirectory } = await Deno.lstat(realPath));
|
||||
}
|
||||
|
||||
if (isSymlink || isDirectory) {
|
||||
yield* walk(path, {
|
||||
maxDepth: maxDepth - 1,
|
||||
includeFiles,
|
||||
includeDirs,
|
||||
includeSymlinks,
|
||||
followSymlinks,
|
||||
exts,
|
||||
match,
|
||||
skip,
|
||||
});
|
||||
} else if (includeFiles && include(path, exts, match, skip)) {
|
||||
yield { path, ...entry };
|
||||
}
|
||||
} catch (err) {
|
||||
throw wrapErrorWithPath(err, normalize(root));
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,12 +899,7 @@ export function* walkSync(
|
||||
if (maxDepth < 1 || !include(root, undefined, undefined, skip)) {
|
||||
return;
|
||||
}
|
||||
let entries;
|
||||
try {
|
||||
entries = Deno.readDirSync(root);
|
||||
} catch (err) {
|
||||
throw wrapErrorWithPath(err, normalize(root));
|
||||
}
|
||||
const entries = Deno.readDirSync(root);
|
||||
for (const entry of entries) {
|
||||
let path = join(root, entry.name);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
import { walk, WalkError, type WalkOptions, walkSync } from "./walk.ts";
|
||||
import { walk, type WalkOptions, walkSync } from "./walk.ts";
|
||||
import {
|
||||
assertArrayIncludes,
|
||||
assertEquals,
|
||||
@ -234,16 +234,19 @@ Deno.test({
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test("walk() rejects with WalkError when root is removed during execution", async () => {
|
||||
Deno.test("walk() rejects with `Deno.errors.NotFound` when root is removed during execution", async () => {
|
||||
const root = resolve(testdataDir, "error");
|
||||
await Deno.mkdir(root);
|
||||
try {
|
||||
await assertRejects(async () => {
|
||||
await Array.fromAsync(
|
||||
walk(root),
|
||||
async () => await Deno.remove(root, { recursive: true }),
|
||||
);
|
||||
}, WalkError);
|
||||
await assertRejects(
|
||||
async () => {
|
||||
await Array.fromAsync(
|
||||
walk(root),
|
||||
async () => await Deno.remove(root, { recursive: true }),
|
||||
);
|
||||
},
|
||||
Deno.errors.NotFound,
|
||||
);
|
||||
} catch (err) {
|
||||
await Deno.remove(root, { recursive: true });
|
||||
throw err;
|
||||
|
Loading…
Reference in New Issue
Block a user