From b6ca4bd1e0e49321626bb6cf1f352feb8b4bfc62 Mon Sep 17 00:00:00 2001 From: Frederik Bosch <6979916+fbosch@users.noreply.github.com> Date: Wed, 4 Feb 2026 18:46:42 +0100 Subject: [PATCH 1/2] fix(targets): use relative symlinks on non-Win --- src/cache/targets.ts | 6 +++++- tests/targets.test.js | 27 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/cache/targets.ts b/src/cache/targets.ts index 1dd56b4..9ffdf01 100644 --- a/src/cache/targets.ts +++ b/src/cache/targets.ts @@ -69,7 +69,11 @@ export const applyTargetDir = async (params: TargetParams) => { const type = process.platform === "win32" ? "junction" : "dir"; try { - await deps.symlink(sourceDir, params.targetDir, type); + const linkTarget = + process.platform === "win32" + ? sourceDir + : path.relative(parentDir, sourceDir); + await deps.symlink(linkTarget, params.targetDir, type); } catch (error) { const code = getErrnoCode(error); const fallbackCodes = new Set(["EPERM", "EACCES", "ENOTSUP", "EINVAL"]); diff --git a/tests/targets.test.js b/tests/targets.test.js index 597bc7e..c927e75 100644 --- a/tests/targets.test.js +++ b/tests/targets.test.js @@ -1,5 +1,5 @@ import assert from "node:assert/strict"; -import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises"; +import { cp, mkdir, readFile, readlink, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { test } from "node:test"; @@ -45,3 +45,28 @@ test("applyTargetDir warns and falls back to copy when symlink fails", async () assert.equal(data, "hello"); assert.match(stderr, /Warning: Failed to create symlink/i); }); + +test("applyTargetDir uses relative symlink targets on non-Windows", async (t) => { + if (process.platform === "win32") { + t.skip("Relative symlink targets are not used on Windows."); + } + const tmpRoot = path.join( + tmpdir(), + `docs-cache-target-relative-${Date.now().toString(36)}`, + ); + const sourceDir = path.join(tmpRoot, "source"); + const targetDir = path.join(tmpRoot, "target"); + const parentDir = path.dirname(targetDir); + + await mkdir(sourceDir, { recursive: true }); + await writeFile(path.join(sourceDir, "README.md"), "hello", "utf8"); + + await applyTargetDir({ + sourceDir, + targetDir, + mode: "symlink", + }); + + const linkTarget = await readlink(targetDir); + assert.equal(linkTarget, path.relative(parentDir, sourceDir)); +}); From 54d8d3c50f002e373eda81a69d13f7a830b6f4fa Mon Sep 17 00:00:00 2001 From: Frederik Bosch <6979916+fbosch@users.noreply.github.com> Date: Wed, 4 Feb 2026 18:54:26 +0100 Subject: [PATCH 2/2] test: skip symlink test on windows --- tests/targets.test.js | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/tests/targets.test.js b/tests/targets.test.js index c927e75..d6f7ce8 100644 --- a/tests/targets.test.js +++ b/tests/targets.test.js @@ -46,27 +46,28 @@ test("applyTargetDir warns and falls back to copy when symlink fails", async () assert.match(stderr, /Warning: Failed to create symlink/i); }); -test("applyTargetDir uses relative symlink targets on non-Windows", async (t) => { - if (process.platform === "win32") { - t.skip("Relative symlink targets are not used on Windows."); - } - const tmpRoot = path.join( - tmpdir(), - `docs-cache-target-relative-${Date.now().toString(36)}`, - ); - const sourceDir = path.join(tmpRoot, "source"); - const targetDir = path.join(tmpRoot, "target"); - const parentDir = path.dirname(targetDir); +test( + "applyTargetDir uses relative symlink targets on non-Windows", + { skip: process.platform === "win32" }, + async () => { + const tmpRoot = path.join( + tmpdir(), + `docs-cache-target-relative-${Date.now().toString(36)}`, + ); + const sourceDir = path.join(tmpRoot, "source"); + const targetDir = path.join(tmpRoot, "target"); + const parentDir = path.dirname(targetDir); - await mkdir(sourceDir, { recursive: true }); - await writeFile(path.join(sourceDir, "README.md"), "hello", "utf8"); + await mkdir(sourceDir, { recursive: true }); + await writeFile(path.join(sourceDir, "README.md"), "hello", "utf8"); - await applyTargetDir({ - sourceDir, - targetDir, - mode: "symlink", - }); + await applyTargetDir({ + sourceDir, + targetDir, + mode: "symlink", + }); - const linkTarget = await readlink(targetDir); - assert.equal(linkTarget, path.relative(parentDir, sourceDir)); -}); + const linkTarget = await readlink(targetDir); + assert.equal(linkTarget, path.relative(parentDir, sourceDir)); + }, +);