fix(reference): bind Git metadata joins to physical directories

This commit is contained in:
morluto committed 2026-10-24 02:35:35 +08:00
1 parent b5e43edf7f
commit 5c16a85a67
2 files changed
+45 -5

No files matched your search

+13 -4
View File
@@ -1,4 +1,4 @@
import { lstat } from "node:fs/promises";
import { lstat, realpath } from "node:fs/promises";
import { dirname, join } from "node:path";
import { absoluteCallerPath } from "../filesystem/callerPath.js";
@@ -29,20 +29,29 @@ export const locateReferenceSourceGitDirectory = async (
repository = parent;
continue;
}
let gitDirectory = dotgit;
let selectedGitDirectory = dotgit;
if (metadata.isFile()) {
const pointer = (await readText(dotgit)).replace(/\r?\n$/u, "");
if (!pointer.startsWith("gitdir: ") || pointer.length === 8)
throw new Error("Invalid Git directory pointer");
gitDirectory = absoluteCallerPath(pointer.slice(8), { cwd: repository });
selectedGitDirectory = absoluteCallerPath(pointer.slice(8), {
cwd: repository,
});
}
// Derived joins and the Git library normalize paths lexically. Admit the
// physical directory first, while the source pointer stays in its file.
const gitDirectory = await realpath(selectedGitDirectory);
let commonDirectory = gitDirectory;
try {
const common = (await readText(join(gitDirectory, "commondir"))).replace(
/\r?\n$/u,
"",
);
commonDirectory = absoluteCallerPath(common, { cwd: gitDirectory });
if (common.length === 0)
throw new Error("Invalid Git common-directory pointer");
commonDirectory = await realpath(
absoluteCallerPath(common, { cwd: gitDirectory }),
);
} catch (cause: unknown) {
if (!hasCode(cause, "ENOENT")) throw cause;
}
@@ -1,4 +1,4 @@
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { mkdir, readFile, symlink, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
@@ -124,3 +124,34 @@ it.each([false, true])(
);
},
);
it.skipIf(process.platform === "win32")(
"binds Git pointer/configuration reads to physical symlink-parent selection",
async () => {
const root = await createTestTempDirectory("rea-reference-git-parent-");
const source = join(root, "source");
const physical = join(root, "physical");
await mkdir(source);
await mkdir(join(physical, "child"), { recursive: true });
await mkdir(join(physical, "metadata"));
await mkdir(join(source, "metadata"));
await symlink(join(physical, "child"), join(source, "alias"));
const intendedHead = "1".repeat(40);
for (const [directory, head, ignoreCase] of [
[join(physical, "metadata"), intendedHead, false],
[join(source, "metadata"), "2".repeat(40), true],
] as const) {
await writeFile(join(directory, "HEAD"), `${head}\n`);
await writeFile(
join(directory, "config"),
`[core]\nignorecase = ${String(ignoreCase)}\n`,
);
}
await writeFile(join(source, ".git"), "gitdir: alias/../metadata\n");
await writeFile(join(source, ".gitignore"), "*.TMP\n");
await writeFile(join(source, "lower.tmp"), "selected policy\n");
const graph = await importTree(source);
expect(graph.entries.some(({ path }) => path === "lower.tmp")).toBe(true);
expect(graph.vcs).toMatchObject({ kind: "git", head: intendedHead });
},
);