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:
parent
1ea76ca797
commit
24f41f67bd
6 changed files with 169 additions and 14 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
});
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 });
|
||||
});
|
||||
|
|
17
fs/utils.ts
17
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue