From 86524921ef1022f4798b6085d0f1904f578b3b58 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] fix(fs): no root path in walk error This adds the root path to error message. Fix #863 --- fs/walk.ts | 104 ++++++++++++++++++++++++++++-------------------- fs/walk_test.ts | 46 ++++++++++++++++++++- 2 files changed, 105 insertions(+), 45 deletions(-) diff --git a/fs/walk.ts b/fs/walk.ts index 4ce564435410c..98f5754e8e912 100644 --- a/fs/walk.ts +++ b/fs/walk.ts @@ -105,33 +105,41 @@ 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) { + if (!err.root) { + err.root = root; + err.message = `${err.message} for path "${root}"` + } + throw err; } } @@ -157,32 +165,40 @@ export function* walkSync( if (maxDepth < 1 || !include(root, undefined, undefined, skip)) { return; } - for (const entry of Deno.readDirSync(root)) { - assert(entry.name != null); - let path = join(root, entry.name); + try { + for (const entry of Deno.readDirSync(root)) { + assert(entry.name != null); + let path = join(root, entry.name); - if (entry.isSymlink) { - if (followSymlinks) { - path = Deno.realPathSync(path); - } else { - continue; + if (entry.isSymlink) { + if (followSymlinks) { + path = Deno.realPathSync(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* walkSync(path, { + maxDepth: maxDepth - 1, + includeFiles, + includeDirs, + followSymlinks, + exts, + match, + skip, + }); } - } else { - yield* walkSync(path, { - maxDepth: maxDepth - 1, - includeFiles, - includeDirs, - followSymlinks, - exts, - match, - skip, - }); } + } catch (err) { + if (!err.root) { + err.root = root; + err.message = `${err.message} for path "${root}"` + } + throw err; } } diff --git a/fs/walk_test.ts b/fs/walk_test.ts index 48e20c450c3c6..116c2722f2182 100644 --- a/fs/walk_test.ts +++ b/fs/walk_test.ts @@ -1,6 +1,12 @@ // 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, + assertObjectMatch, + assertThrows, + assertThrowsAsync, +} from "../testing/asserts.ts"; export function testWalk( setup: (arg0: string) => void | Promise, @@ -260,3 +266,41 @@ 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); + } + }, +);