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..d6f7ce8 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,29 @@ 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", + { 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 applyTargetDir({ + sourceDir, + targetDir, + mode: "symlink", + }); + + const linkTarget = await readlink(targetDir); + assert.equal(linkTarget, path.relative(parentDir, sourceDir)); + }, +);