feat(fs/walk): show path in walk error (#875)

Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
Aurélien Bertron 2021-04-30 08:49:41 +02:00 committed by GitHub
parent d2f076b9d9
commit a0984a6863
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 25 deletions

View File

@ -60,6 +60,13 @@ function include(
return true;
}
function wrapErrorWithRootPath(err: Error & { root: string }, root: string) {
if (err.root) return err;
err.root = root;
err.message = `${err.message} for path "${root}"`;
return err;
}
export interface WalkEntry extends Deno.DirEntry {
path: string;
}
@ -105,33 +112,37 @@ export async function* walk(
if (maxDepth < 1 || !include(root, undefined, undefined, skip)) {
return;
}
for await (const entry of Deno.readDir(root)) {
assert(entry.name != null);
let path = join(root, entry.name);
try {
for await (const entry of Deno.readDir(root)) {
assert(entry.name != null);
let path = join(root, entry.name);
if (entry.isSymlink) {
if (followSymlinks) {
path = await Deno.realPath(path);
if (entry.isSymlink) {
if (followSymlinks) {
path = await Deno.realPath(path);
} else {
continue;
}
}
if (entry.isFile) {
if (includeFiles && include(path, exts, match, skip)) {
yield { path, ...entry };
}
} else {
continue;
yield* walk(path, {
maxDepth: maxDepth - 1,
includeFiles,
includeDirs,
followSymlinks,
exts,
match,
skip,
});
}
}
if (entry.isFile) {
if (includeFiles && include(path, exts, match, skip)) {
yield { path, ...entry };
}
} else {
yield* walk(path, {
maxDepth: maxDepth - 1,
includeFiles,
includeDirs,
followSymlinks,
exts,
match,
skip,
});
}
} catch (err) {
throw wrapErrorWithRootPath(err, normalize(root));
}
}
@ -157,7 +168,13 @@ export function* walkSync(
if (maxDepth < 1 || !include(root, undefined, undefined, skip)) {
return;
}
for (const entry of Deno.readDirSync(root)) {
let entries;
try {
entries = Deno.readDirSync(root);
} catch (err) {
throw wrapErrorWithRootPath(err, normalize(root));
}
for (const entry of entries) {
assert(entry.name != null);
let path = join(root, entry.name);

View File

@ -1,6 +1,11 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
import { walk, WalkEntry, WalkOptions, walkSync } from "./walk.ts";
import { assert, assertEquals, assertThrowsAsync } from "../testing/asserts.ts";
import {
assert,
assertEquals,
assertThrows,
assertThrowsAsync,
} from "../testing/asserts.ts";
export function testWalk(
setup: (arg0: string) => void | Promise<void>,
@ -260,3 +265,47 @@ testWalk(
assert(arr.some((f): boolean => f.endsWith("/b/z")));
},
);
testWalk(
async (d: string) => {
await Deno.mkdir(d + "/a/b", { recursive: true });
await Deno.chmod(d + "/a/b", 0o000);
},
async function subDirNoPermissionAsync() {
try {
await assertThrowsAsync(
async () => {
await walkArray("a");
},
Deno.errors.PermissionDenied,
'for path "a/b"',
);
} finally {
await Deno.chmod("a/b", 0o755);
}
},
// TODO(kt3k): Enable this test on windows when Deno.chmod is implemented
Deno.build.os === "windows",
);
testWalk(
async (d: string) => {
await Deno.mkdir(d + "/a/b", { recursive: true });
await Deno.chmod(d + "/a/b", 0o000);
},
async function subDirNoPermissionSync() {
try {
assertThrows(
() => {
return [...walkSync("a")];
},
Deno.errors.PermissionDenied,
'for path "a/b"',
);
} finally {
await Deno.chmod("a/b", 0o755);
}
},
// TODO(kt3k): Enable this test on windows when Deno.chmod is implemented
Deno.build.os === "windows",
);