diff options
author | Axetroy <axetroy.dev@gmail.com> | 2019-12-18 18:12:36 +0800 |
---|---|---|
committer | Ry Dahl <ry@tinyclouds.org> | 2019-12-18 05:12:36 -0500 |
commit | bb24fb74ffe0bb35649e0adbb1473458c8abf71f (patch) | |
tree | 4eaf1b19f5e505b2cad2ea2cda5ad28cb2104f35 /std/fs | |
parent | 3115781e4316653ab3619e3d94bdbce01fca4ec2 (diff) |
fix permission errors are swallowed by fs.emptyDir (#3501)
Diffstat (limited to 'std/fs')
-rw-r--r-- | std/fs/empty_dir.ts | 65 | ||||
-rw-r--r-- | std/fs/empty_dir_test.ts | 113 | ||||
-rw-r--r-- | std/fs/testdata/empty_dir.ts | 9 | ||||
-rw-r--r-- | std/fs/testdata/empty_dir_sync.ts | 8 |
4 files changed, 172 insertions, 23 deletions
diff --git a/std/fs/empty_dir.ts b/std/fs/empty_dir.ts index 81bc45839..ded02b7e4 100644 --- a/std/fs/empty_dir.ts +++ b/std/fs/empty_dir.ts @@ -1,25 +1,39 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +import { join } from "../path/mod.ts"; +const { + readDir, + readDirSync, + mkdir, + mkdirSync, + remove, + removeSync, + ErrorKind +} = Deno; /** * Ensures that a directory is empty. * Deletes directory contents if the directory is not empty. * If the directory does not exist, it is created. * The directory itself is not deleted. + * Requires the `--allow-read` and `--alow-write` flag. */ export async function emptyDir(dir: string): Promise<void> { - let items: Deno.FileInfo[] = []; try { - items = await Deno.readDir(dir); - } catch { - // if not exist. then create it - await Deno.mkdir(dir, true); - return; - } - while (items.length) { - const item = items.shift(); - if (item && item.name) { - const fn = dir + "/" + item.name; - await Deno.remove(fn, { recursive: true }); + const items = await readDir(dir); + + while (items.length) { + const item = items.shift(); + if (item && item.name) { + const filepath = join(dir, item.name); + await remove(filepath, { recursive: true }); + } + } + } catch (err) { + if ((err as Deno.DenoError<Deno.ErrorKind>).kind !== ErrorKind.NotFound) { + throw err; } + + // if not exist. then create it + await mkdir(dir, true); } } @@ -28,21 +42,26 @@ export async function emptyDir(dir: string): Promise<void> { * Deletes directory contents if the directory is not empty. * If the directory does not exist, it is created. * The directory itself is not deleted. + * Requires the `--allow-read` and `--alow-write` flag. */ export function emptyDirSync(dir: string): void { - let items: Deno.FileInfo[] = []; try { - items = Deno.readDirSync(dir); - } catch { + const items = readDirSync(dir); + + // if directory already exist. then remove it's child item. + while (items.length) { + const item = items.shift(); + if (item && item.name) { + const filepath = join(dir, item.name); + removeSync(filepath, { recursive: true }); + } + } + } catch (err) { + if ((err as Deno.DenoError<Deno.ErrorKind>).kind !== ErrorKind.NotFound) { + throw err; + } // if not exist. then create it - Deno.mkdirSync(dir, true); + mkdirSync(dir, true); return; } - while (items.length) { - const item = items.shift(); - if (item && item.name) { - const fn = dir + "/" + item.name; - Deno.removeSync(fn, { recursive: true }); - } - } } diff --git a/std/fs/empty_dir_test.ts b/std/fs/empty_dir_test.ts index ac5b13476..d25461ce3 100644 --- a/std/fs/empty_dir_test.ts +++ b/std/fs/empty_dir_test.ts @@ -123,3 +123,116 @@ test(function emptyDirSyncIfItExist(): void { Deno.removeSync(testDir, { recursive: true }); } }); + +test(async function emptyDirPermission(): Promise<void> { + interface Scenes { + read: boolean; // --allow-read + write: boolean; // --allow-write + async: boolean; + output: string; + } + + const testfolder = path.join(testdataDir, "testfolder"); + + await Deno.mkdir(testfolder); + + await Deno.writeFile( + path.join(testfolder, "child.txt"), + new TextEncoder().encode("hello world") + ); + + const scenes: Scenes[] = [ + // 1 + { + read: false, + write: false, + async: true, + output: "run again with the --allow-read flag" + }, + { + read: false, + write: false, + async: false, + output: "run again with the --allow-read flag" + }, + // 2 + { + read: true, + write: false, + async: true, + output: "run again with the --allow-write flag" + }, + { + read: true, + write: false, + async: false, + output: "run again with the --allow-write flag" + }, + // 3 + { + read: false, + write: true, + async: true, + output: "run again with the --allow-read flag" + }, + { + read: false, + write: true, + async: false, + output: "run again with the --allow-read flag" + }, + // 4 + { + read: true, + write: true, + async: true, + output: "success" + }, + { + read: true, + write: true, + async: false, + output: "success" + } + ]; + + try { + for (const s of scenes) { + console.log( + `test ${s.async ? "emptyDir" : "emptyDirSync"}("testdata/testfolder") ${ + s.read ? "with" : "without" + } --allow-read & ${s.write ? "with" : "without"} --allow-write` + ); + + const args = [Deno.execPath(), "run"]; + + if (s.read) { + args.push("--allow-read"); + } + + if (s.write) { + args.push("--allow-write"); + } + + args.push( + path.join(testdataDir, s.async ? "empty_dir.ts" : "empty_dir_sync.ts") + ); + args.push("testfolder"); + + const { stdout } = Deno.run({ + stdout: "piped", + cwd: testdataDir, + args: args + }); + + const output = await Deno.readAll(stdout); + + assertEquals(new TextDecoder().decode(output), s.output); + } + } catch (err) { + await Deno.remove(testfolder, { recursive: true }); + throw err; + } + + // done +}); diff --git a/std/fs/testdata/empty_dir.ts b/std/fs/testdata/empty_dir.ts new file mode 100644 index 000000000..6147679da --- /dev/null +++ b/std/fs/testdata/empty_dir.ts @@ -0,0 +1,9 @@ +import { emptyDir } from "../empty_dir.ts"; + +emptyDir(Deno.args[1]) + .then(() => { + Deno.stdout.write(new TextEncoder().encode("success")) + }) + .catch((err) => { + Deno.stdout.write(new TextEncoder().encode(err.message)) + })
\ No newline at end of file diff --git a/std/fs/testdata/empty_dir_sync.ts b/std/fs/testdata/empty_dir_sync.ts new file mode 100644 index 000000000..3c0eb9031 --- /dev/null +++ b/std/fs/testdata/empty_dir_sync.ts @@ -0,0 +1,8 @@ +import { emptyDirSync } from "../empty_dir.ts"; + +try { + emptyDirSync(Deno.args[1]) + Deno.stdout.write(new TextEncoder().encode("success")) +} catch (err) { + Deno.stdout.write(new TextEncoder().encode(err.message)) +}
\ No newline at end of file |