1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-27 01:29:14 -05:00

fix: ensure exists file/dir must be the same type or it will throw error (#294)

This commit is contained in:
Axetroy 2019-04-07 09:01:23 +08:00 committed by Ryan Dahl
parent 1ea76ca797
commit 24f41f67bd
6 changed files with 169 additions and 14 deletions

View file

@ -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);
}

View file

@ -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 });
});

View file

@ -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));

View file

@ -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 });
});

View file

@ -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;
}

View file

@ -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);
});
});