From a5a68a3ec09c097643533945e0b526900940610e Mon Sep 17 00:00:00 2001 From: Chris Knight Date: Fri, 29 May 2020 00:39:02 +0100 Subject: [PATCH] feat(std/node): add link/linkSync polyfill (denoland/deno#5930) --- node/_fs/_fs_link.ts | 37 +++++++++++++++++++++ node/_fs/_fs_link_test.ts | 67 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 node/_fs/_fs_link.ts create mode 100644 node/_fs/_fs_link_test.ts diff --git a/node/_fs/_fs_link.ts b/node/_fs/_fs_link.ts new file mode 100644 index 0000000000000..50916a7ba0d7e --- /dev/null +++ b/node/_fs/_fs_link.ts @@ -0,0 +1,37 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +import { CallbackWithError } from "./_fs_common.ts"; +import { fromFileUrl } from "../path.ts"; + +/** + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these + * are implemented. See https://github.com/denoland/deno/issues/3403 + */ +export function link( + existingPath: string | URL, + newPath: string | URL, + callback: CallbackWithError +): void { + existingPath = + existingPath instanceof URL ? fromFileUrl(existingPath) : existingPath; + newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath; + + Deno.link(existingPath, newPath) + .then(() => callback()) + .catch(callback); +} + +/** + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these + * are implemented. See https://github.com/denoland/deno/issues/3403 + */ +export function linkSync( + existingPath: string | URL, + newPath: string | URL +): void { + existingPath = + existingPath instanceof URL ? fromFileUrl(existingPath) : existingPath; + newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath; + + Deno.linkSync(existingPath, newPath); +} diff --git a/node/_fs/_fs_link_test.ts b/node/_fs/_fs_link_test.ts new file mode 100644 index 0000000000000..e59984c8cbcfb --- /dev/null +++ b/node/_fs/_fs_link_test.ts @@ -0,0 +1,67 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +const { test } = Deno; +import { fail, assertEquals } from "../../testing/asserts.ts"; +import { link, linkSync } from "./_fs_link.ts"; +import { assert } from "https://deno.land/std@v0.50.0/testing/asserts.ts"; +const isWindows = Deno.build.os === "windows"; + +test({ + ignore: isWindows, + name: "ASYNC: hard linking files works as expected", + async fn() { + const tempFile: string = await Deno.makeTempFile(); + const linkedFile: string = tempFile + ".link"; + await new Promise((res, rej) => { + link(tempFile, linkedFile, (err) => { + if (err) rej(err); + else res(); + }); + }) + .then(() => { + assertEquals(Deno.statSync(tempFile), Deno.statSync(linkedFile)); + }) + .catch(() => { + fail("Expected to succeed"); + }) + .finally(() => { + Deno.removeSync(tempFile); + Deno.removeSync(linkedFile); + }); + }, +}); + +test({ + ignore: isWindows, + name: "ASYNC: hard linking files passes error to callback", + async fn() { + let failed = false; + await new Promise((res, rej) => { + link("no-such-file", "no-such-file", (err) => { + if (err) rej(err); + else res(); + }); + }) + .then(() => { + fail("Expected to succeed"); + }) + .catch((err) => { + assert(err); + failed = true; + }); + assert(failed); + }, +}); + +test({ + ignore: isWindows, + name: "SYNC: hard linking files works as expected", + fn() { + const tempFile: string = Deno.makeTempFileSync(); + const linkedFile: string = tempFile + ".link"; + linkSync(tempFile, linkedFile); + + assertEquals(Deno.statSync(tempFile), Deno.statSync(linkedFile)); + Deno.removeSync(tempFile); + Deno.removeSync(linkedFile); + }, +});