summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAxetroy <troy450409405@gmail.com>2019-04-07 09:01:23 +0800
committerRyan Dahl <ry@tinyclouds.org>2019-04-07 04:01:23 +0300
commitd6f808958f414315a09b3429cf0c4b5c258f1012 (patch)
treed2d60398319ba1bcd3f11216b258d835941ef45f
parent9d1e24b67baf59d1d8b9bd1eb2a6c4135c6e7ca4 (diff)
fix: ensure exists file/dir must be the same type or it will throw error (denoland/deno_std#294)
Original: https://github.com/denoland/deno_std/commit/24f41f67bdbc9f426e3f9f03598a1010748d8200
-rw-r--r--fs/ensure_dir.ts30
-rw-r--r--fs/ensure_dir_test.ts40
-rw-r--r--fs/ensure_file.ts29
-rw-r--r--fs/ensure_file_test.ts32
-rw-r--r--fs/utils.ts17
-rw-r--r--fs/utils_test.ts35
6 files changed, 169 insertions, 14 deletions
diff --git a/fs/ensure_dir.ts b/fs/ensure_dir.ts
index e7e4f69a2..dfc02f35c 100644
--- a/fs/ensure_dir.ts
+++ b/fs/ensure_dir.ts
@@ -1,14 +1,24 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-
+import { getFileInfoType } from "./utils.ts";
/**
* Ensures that the directory exists.
* If the directory structure does not exist, it is created. Like mkdir -p.
*/
export async function ensureDir(dir: string): Promise<void> {
+ let pathExists = false;
try {
// if dir exists
- await Deno.stat(dir);
- } catch {
+ const stat = await Deno.stat(dir);
+ pathExists = true;
+ if (!stat.isDirectory()) {
+ throw new Error(
+ `Ensure path exists, expected 'dir', got '${getFileInfoType(stat)}'`
+ );
+ }
+ } catch (err) {
+ if (pathExists) {
+ throw err;
+ }
// if dir not exists. then create it.
await Deno.mkdir(dir, true);
}
@@ -19,10 +29,20 @@ export async function ensureDir(dir: string): Promise<void> {
* If the directory structure does not exist, it is created. Like mkdir -p.
*/
export function ensureDirSync(dir: string): void {
+ let pathExists = false;
try {
// if dir exists
- Deno.statSync(dir);
- } catch {
+ const stat = Deno.statSync(dir);
+ pathExists = true;
+ if (!stat.isDirectory()) {
+ throw new Error(
+ `Ensure path exists, expected 'dir', got '${getFileInfoType(stat)}'`
+ );
+ }
+ } catch (err) {
+ if (pathExists) {
+ throw err;
+ }
// if dir not exists. then create it.
Deno.mkdirSync(dir, true);
}
diff --git a/fs/ensure_dir_test.ts b/fs/ensure_dir_test.ts
index 2e7936ae9..3426588b7 100644
--- a/fs/ensure_dir_test.ts
+++ b/fs/ensure_dir_test.ts
@@ -3,6 +3,7 @@ import { test } from "../testing/mod.ts";
import { assertThrows, assertThrowsAsync } from "../testing/asserts.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import * as path from "./path/mod.ts";
+import { ensureFile, ensureFileSync } from "./ensure_file.ts";
const testdataDir = path.resolve("fs", "testdata");
@@ -27,10 +28,7 @@ test(function ensureDirSyncIfItNotExist() {
ensureDirSync(testDir);
- assertThrows(() => {
- Deno.statSync(testDir);
- throw new Error("test dir should exists.");
- });
+ Deno.statSync(testDir);
Deno.removeSync(baseDir, { recursive: true });
});
@@ -69,3 +67,37 @@ test(function ensureDirSyncIfItExist() {
Deno.removeSync(baseDir, { recursive: true });
});
+
+test(async function ensureDirIfItAsFile() {
+ const baseDir = path.join(testdataDir, "ensure_dir_exist_file");
+ const testFile = path.join(baseDir, "test");
+
+ await ensureFile(testFile);
+
+ await assertThrowsAsync(
+ async () => {
+ await ensureDir(testFile);
+ },
+ Error,
+ `Ensure path exists, expected 'dir', got 'file'`
+ );
+
+ await Deno.remove(baseDir, { recursive: true });
+});
+
+test(function ensureDirSyncIfItAsFile() {
+ const baseDir = path.join(testdataDir, "ensure_dir_exist_file_async");
+ const testFile = path.join(baseDir, "test");
+
+ ensureFileSync(testFile);
+
+ assertThrows(
+ () => {
+ ensureDirSync(testFile);
+ },
+ Error,
+ `Ensure path exists, expected 'dir', got 'file'`
+ );
+
+ Deno.removeSync(baseDir, { recursive: true });
+});
diff --git a/fs/ensure_file.ts b/fs/ensure_file.ts
index 56632f150..6fe8e7822 100644
--- a/fs/ensure_file.ts
+++ b/fs/ensure_file.ts
@@ -1,6 +1,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import * as path from "./path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
+import { getFileInfoType } from "./utils.ts";
/**
* Ensures that the file exists.
@@ -8,10 +9,20 @@ import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
* these directories are created. If the file already exists, it is NOT MODIFIED.
*/
export async function ensureFile(filePath: string): Promise<void> {
+ let pathExists = false;
try {
// if file exists
- await Deno.stat(filePath);
- } catch {
+ const stat = await Deno.lstat(filePath);
+ pathExists = true;
+ if (!stat.isFile()) {
+ throw new Error(
+ `Ensure path exists, expected 'file', got '${getFileInfoType(stat)}'`
+ );
+ }
+ } catch (err) {
+ if (pathExists) {
+ throw err;
+ }
// if file not exists
// ensure dir exists
await ensureDir(path.dirname(filePath));
@@ -26,10 +37,20 @@ export async function ensureFile(filePath: string): Promise<void> {
* these directories are created. If the file already exists, it is NOT MODIFIED.
*/
export function ensureFileSync(filePath: string): void {
+ let pathExists = false;
try {
// if file exists
- Deno.statSync(filePath);
- } catch {
+ const stat = Deno.statSync(filePath);
+ pathExists = true;
+ if (!stat.isFile()) {
+ throw new Error(
+ `Ensure path exists, expected 'file', got '${getFileInfoType(stat)}'`
+ );
+ }
+ } catch (err) {
+ if (pathExists) {
+ throw err;
+ }
// if file not exists
// ensure dir exists
ensureDirSync(path.dirname(filePath));
diff --git a/fs/ensure_file_test.ts b/fs/ensure_file_test.ts
index 2199e3605..fd3f4718a 100644
--- a/fs/ensure_file_test.ts
+++ b/fs/ensure_file_test.ts
@@ -69,3 +69,35 @@ test(function ensureFileSyncIfItExist() {
Deno.removeSync(testDir, { recursive: true });
});
+
+test(async function ensureFileIfItExistAsDir() {
+ const testDir = path.join(testdataDir, "ensure_file_5");
+
+ await Deno.mkdir(testDir, true);
+
+ await assertThrowsAsync(
+ async () => {
+ await ensureFile(testDir);
+ },
+ Error,
+ `Ensure path exists, expected 'file', got 'dir'`
+ );
+
+ await Deno.remove(testDir, { recursive: true });
+});
+
+test(function ensureFileSyncIfItExistAsDir() {
+ const testDir = path.join(testdataDir, "ensure_file_6");
+
+ Deno.mkdirSync(testDir, true);
+
+ assertThrows(
+ () => {
+ ensureFileSync(testDir);
+ },
+ Error,
+ `Ensure path exists, expected 'file', got 'dir'`
+ );
+
+ Deno.removeSync(testDir, { recursive: true });
+});
diff --git a/fs/utils.ts b/fs/utils.ts
index dd7ee5fa4..410e45909 100644
--- a/fs/utils.ts
+++ b/fs/utils.ts
@@ -21,3 +21,20 @@ export function isSubdir(
return acc && destArray[i] === current;
}, true);
}
+
+export enum PathType {
+ file = "file",
+ dir = "dir",
+ symlink = "symlink"
+}
+
+/* Get a human readable file type string */
+export function getFileInfoType(fileInfo: Deno.FileInfo): PathType | null {
+ return fileInfo.isFile()
+ ? PathType.file
+ : fileInfo.isDirectory()
+ ? PathType.dir
+ : fileInfo.isSymlink()
+ ? PathType.symlink
+ : null;
+}
diff --git a/fs/utils_test.ts b/fs/utils_test.ts
index 9d6959de5..9f8d10cb0 100644
--- a/fs/utils_test.ts
+++ b/fs/utils_test.ts
@@ -2,8 +2,12 @@
import { test } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts";
-import { isSubdir } from "./utils.ts";
+import { isSubdir, getFileInfoType, PathType } from "./utils.ts";
import * as path from "./path/mod.ts";
+import { ensureFileSync } from "./ensure_file.ts";
+import { ensureDirSync } from "./ensure_dir.ts";
+
+const testdataDir = path.resolve("fs", "testdata");
test(function _isSubdir() {
const pairs = [
@@ -29,3 +33,32 @@ test(function _isSubdir() {
);
});
});
+
+test(function _getFileInfoType() {
+ const pairs = [
+ [path.join(testdataDir, "file_type_1"), PathType.file],
+ [path.join(testdataDir, "file_type_dir_1"), PathType.dir]
+ ];
+
+ pairs.forEach(function(p) {
+ const filePath = p[0] as string;
+ const type = p[1] as PathType;
+ switch (type) {
+ case PathType.file:
+ ensureFileSync(filePath);
+ break;
+ case PathType.dir:
+ ensureDirSync(filePath);
+ break;
+ case PathType.symlink:
+ // TODO(axetroy): test symlink
+ break;
+ }
+
+ const stat = Deno.statSync(filePath);
+
+ Deno.removeSync(filePath, { recursive: true });
+
+ assertEquals(getFileInfoType(stat), type);
+ });
+});