summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/README.md23
-rw-r--r--fs/ensure_symlink.ts71
-rw-r--r--fs/ensure_symlink_test.ts165
-rw-r--r--fs/test.ts1
4 files changed, 260 insertions, 0 deletions
diff --git a/fs/README.md b/fs/README.md
index 93c95de03..3acf757a8 100644
--- a/fs/README.md
+++ b/fs/README.md
@@ -45,6 +45,29 @@ ensureFile("./folder/targetFile.dat"); // returns promise
ensureFileSync("./folder/targetFile.dat"); // void
```
+### ensureSymlink
+
+Ensures that the link exists.
+If the directory structure does not exist, it is created.
+
+```ts
+import {
+ ensureSymlink,
+ ensureSymlinkSync
+} from "https://deno.land/std/fs/mod.ts";
+
+ensureSymlink(
+ "./folder/targetFile.dat",
+ "./folder/targetFile.link.dat",
+ "file"
+); // returns promise
+ensureSymlinkSync(
+ "./folder/targetFile.dat",
+ "./folder/targetFile.link.dat",
+ "file"
+); // void
+```
+
### eol
Detects and format the passed string for the targeted End Of Line character.
diff --git a/fs/ensure_symlink.ts b/fs/ensure_symlink.ts
new file mode 100644
index 000000000..fbb89948e
--- /dev/null
+++ b/fs/ensure_symlink.ts
@@ -0,0 +1,71 @@
+// 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 { exists, existsSync } from "./exists.ts";
+import { PathType, getFileInfoType } from "./utils.ts";
+
+const isWindows = Deno.platform.os === "win";
+
+/**
+ * Ensures that the link exists.
+ * If the directory structure does not exist, it is created.
+ *
+ * @param src the source file path
+ * @param dest the destination link path
+ */
+export async function ensureSymlink(src: string, dest: string): Promise<void> {
+ const srcStatInfo = await Deno.lstat(src);
+ const srcFilePathType = getFileInfoType(srcStatInfo);
+
+ if (await exists(dest)) {
+ const destStatInfo = await Deno.lstat(dest);
+ const destFilePathType = getFileInfoType(destStatInfo);
+ if (destFilePathType !== PathType.symlink) {
+ throw new Error(
+ `Ensure path exists, expected 'symlink', got '${destFilePathType}'`
+ );
+ }
+ return;
+ }
+
+ await ensureDir(path.dirname(dest));
+
+ // TODO(axetroy): remove this if condition. refs: https://github.com/denoland/deno/issues/2169
+ if (isWindows) {
+ await Deno.symlink(src, dest, srcFilePathType || undefined);
+ } else {
+ await Deno.symlink(src, dest);
+ }
+}
+
+/**
+ * Ensures that the link exists.
+ * If the directory structure does not exist, it is created.
+ *
+ * @param src the source file path
+ * @param dest the destination link path
+ */
+export function ensureSymlinkSync(src: string, dest: string): void {
+ const srcStatInfo = Deno.lstatSync(src);
+ const srcFilePathType = getFileInfoType(srcStatInfo);
+
+ if (existsSync(dest)) {
+ const destStatInfo = Deno.lstatSync(dest);
+ const destFilePathType = getFileInfoType(destStatInfo);
+ if (destFilePathType !== PathType.symlink) {
+ throw new Error(
+ `Ensure path exists, expected 'symlink', got '${destFilePathType}'`
+ );
+ }
+ return;
+ }
+
+ ensureDirSync(path.dirname(dest));
+
+ // TODO(axetroy): remove this if condition. refs: https://github.com/denoland/deno/issues/2169
+ if (isWindows) {
+ Deno.symlinkSync(src, dest, srcFilePathType || undefined);
+ } else {
+ Deno.symlinkSync(src, dest);
+ }
+}
diff --git a/fs/ensure_symlink_test.ts b/fs/ensure_symlink_test.ts
new file mode 100644
index 000000000..22be30b88
--- /dev/null
+++ b/fs/ensure_symlink_test.ts
@@ -0,0 +1,165 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+// TODO(axetroy): Add test for Windows once symlink is implemented for Windows.
+import { test } from "../testing/mod.ts";
+import {
+ assertEquals,
+ assertThrows,
+ assertThrowsAsync
+} from "../testing/asserts.ts";
+import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts";
+import * as path from "./path/mod.ts";
+
+const testdataDir = path.resolve("fs", "testdata");
+const isWindows = Deno.platform.os === "win";
+
+test(async function ensureSymlinkIfItNotExist() {
+ const testDir = path.join(testdataDir, "link_file_1");
+ const testFile = path.join(testDir, "test.txt");
+
+ assertThrowsAsync(async () => {
+ await ensureSymlink(testFile, path.join(testDir, "test1.txt"));
+ });
+
+ assertThrowsAsync(async () => {
+ await Deno.stat(testFile).then(() => {
+ throw new Error("test file should exists.");
+ });
+ });
+});
+
+test(function ensureSymlinkSyncIfItNotExist() {
+ const testDir = path.join(testdataDir, "link_file_2");
+ const testFile = path.join(testDir, "test.txt");
+
+ assertThrows(() => {
+ ensureSymlinkSync(testFile, path.join(testDir, "test1.txt"));
+ });
+
+ assertThrows(() => {
+ Deno.statSync(testFile);
+ throw new Error("test file should exists.");
+ });
+});
+
+test(async function ensureSymlinkIfItExist() {
+ const testDir = path.join(testdataDir, "link_file_3");
+ const testFile = path.join(testDir, "test.txt");
+ const linkFile = path.join(testDir, "link.txt");
+
+ await Deno.mkdir(testDir, true);
+ await Deno.writeFile(testFile, new Uint8Array());
+
+ if (isWindows) {
+ await assertThrowsAsync(
+ () => ensureSymlink(testFile, linkFile),
+ Error,
+ "Not implemented"
+ );
+ await Deno.remove(testDir, { recursive: true });
+ return;
+ } else {
+ await ensureSymlink(testFile, linkFile);
+ }
+
+ const srcStat = await Deno.lstat(testFile);
+ const linkStat = await Deno.lstat(linkFile);
+
+ assertEquals(srcStat.isFile(), true);
+ assertEquals(linkStat.isSymlink(), true);
+
+ await Deno.remove(testDir, { recursive: true });
+});
+
+test(function ensureSymlinkSyncIfItExist() {
+ const testDir = path.join(testdataDir, "link_file_4");
+ const testFile = path.join(testDir, "test.txt");
+ const linkFile = path.join(testDir, "link.txt");
+
+ Deno.mkdirSync(testDir, true);
+ Deno.writeFileSync(testFile, new Uint8Array());
+
+ if (isWindows) {
+ assertThrows(
+ () => ensureSymlinkSync(testFile, linkFile),
+ Error,
+ "Not implemented"
+ );
+ Deno.removeSync(testDir, { recursive: true });
+ return;
+ } else {
+ ensureSymlinkSync(testFile, linkFile);
+ }
+
+ const srcStat = Deno.lstatSync(testFile);
+
+ const linkStat = Deno.lstatSync(linkFile);
+
+ assertEquals(srcStat.isFile(), true);
+ assertEquals(linkStat.isSymlink(), true);
+
+ Deno.removeSync(testDir, { recursive: true });
+});
+
+test(async function ensureSymlinkDirectoryIfItExist() {
+ const testDir = path.join(testdataDir, "link_file_origin_3");
+ const linkDir = path.join(testdataDir, "link_file_link_3");
+ const testFile = path.join(testDir, "test.txt");
+
+ await Deno.mkdir(testDir, true);
+ await Deno.writeFile(testFile, new Uint8Array());
+
+ if (isWindows) {
+ await assertThrowsAsync(
+ () => ensureSymlink(testDir, linkDir),
+ Error,
+ "Not implemented"
+ );
+ await Deno.remove(testDir, { recursive: true });
+ return;
+ } else {
+ await ensureSymlink(testDir, linkDir);
+ }
+
+ const testDirStat = await Deno.lstat(testDir);
+ const linkDirStat = await Deno.lstat(linkDir);
+ const testFileStat = await Deno.lstat(testFile);
+
+ assertEquals(testFileStat.isFile(), true);
+ assertEquals(testDirStat.isDirectory(), true);
+ assertEquals(linkDirStat.isSymlink(), true);
+
+ await Deno.remove(linkDir, { recursive: true });
+ await Deno.remove(testDir, { recursive: true });
+});
+
+test(function ensureSymlinkSyncDirectoryIfItExist() {
+ const testDir = path.join(testdataDir, "link_file_origin_3");
+ const linkDir = path.join(testdataDir, "link_file_link_3");
+ const testFile = path.join(testDir, "test.txt");
+
+ Deno.mkdirSync(testDir, true);
+ Deno.writeFileSync(testFile, new Uint8Array());
+
+ if (isWindows) {
+ assertThrows(
+ () => ensureSymlinkSync(testDir, linkDir),
+ Error,
+ "Not implemented"
+ );
+ Deno.removeSync(testDir, { recursive: true });
+ return;
+ } else {
+ ensureSymlinkSync(testDir, linkDir);
+ }
+
+ const testDirStat = Deno.lstatSync(testDir);
+ const linkDirStat = Deno.lstatSync(linkDir);
+ const testFileStat = Deno.lstatSync(testFile);
+
+ assertEquals(testFileStat.isFile(), true);
+ assertEquals(testDirStat.isDirectory(), true);
+ assertEquals(linkDirStat.isSymlink(), true);
+
+ Deno.removeSync(linkDir, { recursive: true });
+ Deno.removeSync(testDir, { recursive: true });
+});
diff --git a/fs/test.ts b/fs/test.ts
index 08c6f2cf8..9f6b4827b 100644
--- a/fs/test.ts
+++ b/fs/test.ts
@@ -8,6 +8,7 @@ import "./eol_test.ts";
import "./empty_dir_test.ts";
import "./ensure_dir_test.ts";
import "./ensure_file_test.ts";
+import "./ensure_symlink_test.ts";
import "./move_test.ts";
import "./read_json_test.ts";
import "./write_json_test.ts";