diff --git a/fs/ensure_symlink.ts b/fs/ensure_symlink.ts index f2dec2cd9ea7..443445f479e4 100644 --- a/fs/ensure_symlink.ts +++ b/fs/ensure_symlink.ts @@ -53,7 +53,17 @@ export async function ensureSymlink( linkName: string | URL, ) { const targetRealPath = resolveSymlinkTarget(target, linkName); - const srcStatInfo = await Deno.lstat(targetRealPath); + let srcStatInfo; + try { + srcStatInfo = await Deno.lstat(targetRealPath); + } catch (error) { + if (error instanceof Deno.errors.NotFound) { + throw new Deno.errors.NotFound( + `Cannot ensure symlink as the target path does not exist: ${targetRealPath}`, + ); + } + throw error; + } const srcFilePathType = getFileInfoType(srcStatInfo); await ensureDir(dirname(toPathString(linkName))); @@ -112,7 +122,17 @@ export function ensureSymlinkSync( linkName: string | URL, ) { const targetRealPath = resolveSymlinkTarget(target, linkName); - const srcStatInfo = Deno.lstatSync(targetRealPath); + let srcStatInfo; + try { + srcStatInfo = Deno.lstatSync(targetRealPath); + } catch (error) { + if (error instanceof Deno.errors.NotFound) { + throw new Deno.errors.NotFound( + `Cannot ensure symlink as the target path does not exist: ${targetRealPath}`, + ); + } + throw error; + } const srcFilePathType = getFileInfoType(srcStatInfo); ensureDirSync(dirname(toPathString(linkName))); diff --git a/fs/ensure_symlink_test.ts b/fs/ensure_symlink_test.ts index 9bf4c4f2212c..4e2ebc27c9d9 100644 --- a/fs/ensure_symlink_test.ts +++ b/fs/ensure_symlink_test.ts @@ -1,6 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // TODO(axetroy): Add test for Windows once symlink is implemented for Windows. -import { assert, assertEquals, assertRejects, assertThrows } from "@std/assert"; +import { + assert, + assertEquals, + assertMatch, + assertRejects, + assertThrows, +} from "@std/assert"; import * as path from "@std/path"; import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts"; import { IS_DENO_2 } from "../internal/_is_deno_2.ts"; @@ -239,6 +245,29 @@ Deno.test("ensureSymlinkSync() creates symlink with relative target", function ( Deno.removeSync(testDir, { recursive: true }); }); +Deno.test("ensureSymlink() rejects when the target path doesn't exist", async () => { + const e = await assertRejects( + async () => { + await ensureSymlink("non-existent-target", "non-existent-link"); + }, + Deno.errors.NotFound, + ); + assertMatch( + e.message, + /^Cannot ensure symlink as the target path does not exist: .*non-existent-target$/, + ); +}); + +Deno.test("ensureSymlinkSync() throws when the target path doesn't exist", async () => { + const e = assertThrows(() => { + ensureSymlinkSync("non-existent-target", "non-existent-link"); + }, Deno.errors.NotFound); + assertMatch( + e.message, + /^Cannot ensure symlink as the target path does not exist: .*non-existent-target$/, + ); +}); + Deno.test("ensureSymlink() works with URLs", { // TODO(kt3k): The 2nd test case doesn't pass on Windows. Fix it. ignore: Deno.build.os === "windows",