From 767d0ae982e3022d4603f53f407039c6c5b529b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Bertron?= Date: Sat, 24 Apr 2021 14:08:05 +0200 Subject: [PATCH 1/3] fix(fs/walk): no root path in error message (#875) This adds the root path to error message. The `root` property is set to properly handle errors in case of recursion. Fix #863 --- fs/walk.ts | 63 +++++++++++++++++++++++++++++++------------------ fs/walk_test.ts | 47 +++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 24 deletions(-) diff --git a/fs/walk.ts b/fs/walk.ts index 4ce564435410..43120c93218f 100644 --- a/fs/walk.ts +++ b/fs/walk.ts @@ -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); - } else { - continue; + 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 }; + 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, + }); } - } 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); diff --git a/fs/walk_test.ts b/fs/walk_test.ts index 48e20c450c3c..28f6eb1c87aa 100644 --- a/fs/walk_test.ts +++ b/fs/walk_test.ts @@ -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, @@ -260,3 +265,43 @@ 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); + } + }, +); + +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); + } + }, +); From 5ca61c7b7abc3c265cb3c5d024c27ab3fde9837e Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 30 Apr 2021 15:33:46 +0900 Subject: [PATCH 2/3] chore: ignore some tests on windows --- fs/walk_test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/walk_test.ts b/fs/walk_test.ts index 28f6eb1c87aa..88c5b43a7283 100644 --- a/fs/walk_test.ts +++ b/fs/walk_test.ts @@ -284,6 +284,8 @@ testWalk( await Deno.chmod("a/b", 0o755); } }, + // TODO(kt3k): Enable this test on windows when Deno.chmod is implemented + Deno.build.os === "windows" ); testWalk( @@ -304,4 +306,6 @@ testWalk( await Deno.chmod("a/b", 0o755); } }, + // TODO(kt3k): Enable this test on windows when Deno.chmod is implemented + Deno.build.os === "windows" ); From 34ef13c58adc935caadc3bbf491da329ca1dae2e Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 30 Apr 2021 15:38:18 +0900 Subject: [PATCH 3/3] chore: fmt --- fs/walk_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/walk_test.ts b/fs/walk_test.ts index 88c5b43a7283..b08d0032cb92 100644 --- a/fs/walk_test.ts +++ b/fs/walk_test.ts @@ -285,7 +285,7 @@ testWalk( } }, // TODO(kt3k): Enable this test on windows when Deno.chmod is implemented - Deno.build.os === "windows" + Deno.build.os === "windows", ); testWalk( @@ -307,5 +307,5 @@ testWalk( } }, // TODO(kt3k): Enable this test on windows when Deno.chmod is implemented - Deno.build.os === "windows" + Deno.build.os === "windows", );