Skip to content

Commit

Permalink
fix permission errors are swallowed by fs.exists (denoland#3493)
Browse files Browse the repository at this point in the history
  • Loading branch information
axetroy authored and ry committed Dec 13, 2019
1 parent df7d828 commit 8cf8a29
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 6 deletions.
25 changes: 19 additions & 6 deletions std/fs/exists.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.

const { lstat, lstatSync, DenoError, ErrorKind } = Deno;
/**
* Test whether or not the given path exists by checking with the file system
*/
export async function exists(filePath: string): Promise<boolean> {
return Deno.lstat(filePath)
return lstat(filePath)
.then((): boolean => true)
.catch((): boolean => false);
.catch((err: Error): boolean => {
if (err instanceof DenoError) {
if (err.kind === ErrorKind.NotFound) {
return false;
}
}

throw err;
});
}

/**
* Test whether or not the given path exists by checking with the file system
*/
export function existsSync(filePath: string): boolean {
try {
Deno.lstatSync(filePath);
lstatSync(filePath);
return true;
} catch {
return false;
} catch (err) {
if (err instanceof DenoError) {
if (err.kind === ErrorKind.NotFound) {
return false;
}
}
throw err;
}
}
93 changes: 93 additions & 0 deletions std/fs/exists_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,96 @@ test(async function existsLink(): Promise<void> {
// in repository
assertEquals(await exists(path.join(testdataDir, "0-link.ts")), true);
});

test(async function existsPermission(): Promise<void> {
interface Scenes {
read: boolean; // --allow-read
async: boolean;
output: string;
file: string; // target file to run
}

const scenes: Scenes[] = [
// 1
{
read: false,
async: true,
output: "run again with the --allow-read flag",
file: "0.ts"
},
{
read: false,
async: false,
output: "run again with the --allow-read flag",
file: "0.ts"
},
// 2
{
read: true,
async: true,
output: "exist",
file: "0.ts"
},
{
read: true,
async: false,
output: "exist",
file: "0.ts"
},
// 3
{
read: false,
async: true,
output: "run again with the --allow-read flag",
file: "no_exist_file_for_test.ts"
},
{
read: false,
async: false,
output: "run again with the --allow-read flag",
file: "no_exist_file_for_test.ts"
},
// 4
{
read: true,
async: true,
output: "not exist",
file: "no_exist_file_for_test.ts"
},
{
read: true,
async: false,
output: "not exist",
file: "no_exist_file_for_test.ts"
}
];

for (const s of scenes) {
console.log(
`test ${s.async ? "exists" : "existsSync"}("testdata/${s.file}") ${
s.read ? "with" : "without"
} --allow-read`
);

const args = [Deno.execPath(), "run"];

if (s.read) {
args.push("--allow-read");
}

args.push(path.join(testdataDir, s.async ? "exists.ts" : "exists_sync.ts"));
args.push(s.file);

const { stdout } = Deno.run({
stdout: "piped",
cwd: testdataDir,
args: args
});

const output = await Deno.readAll(stdout);

assertEquals(new TextDecoder().decode(output), s.output);
}

// done
});
10 changes: 10 additions & 0 deletions std/fs/testdata/exists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { exists } from "../exists.ts";

exists(Deno.args[1])
.then(isExist => {
Deno.stdout.write(new TextEncoder().encode(isExist ? 'exist' :'not exist'))
})
.catch((err) => {
Deno.stdout.write(new TextEncoder().encode(err.message))
})

10 changes: 10 additions & 0 deletions std/fs/testdata/exists_sync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { existsSync } from "../exists.ts";

try {
const isExist = existsSync(Deno.args[1])
Deno.stdout.write(new TextEncoder().encode(isExist ? 'exist' :'not exist'))
} catch (err) {
Deno.stdout.write(new TextEncoder().encode(err.message))
}


0 comments on commit 8cf8a29

Please sign in to comment.