mirror of
https://github.com/morluto/rea
synced 2026-10-26 06:16:17 -04:00
fix(reference): read linked worktree commit provenance (#677)
Signed-off-by: RudyCelekli <47457359+rudycelekli@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
8189081511
commit
d565ecdc25
@@ -1,6 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import { lstat } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { lstat, readFile } from "node:fs/promises";
|
||||
import { join, resolve } from "node:path";
|
||||
|
||||
import { resolveRef } from "isomorphic-git";
|
||||
|
||||
@@ -31,7 +31,7 @@ export const readReferenceSourceVcs = async (
|
||||
: { kind: "unknown", head: null, dirty: null };
|
||||
}
|
||||
try {
|
||||
const head = await resolveRef({ fs, dir: root, ref: "HEAD" });
|
||||
const head = await resolveSourceHead(root);
|
||||
if (isAborted(signal)) return { kind: "unknown", head: null, dirty: null };
|
||||
return { kind: "git", head, dirty: null };
|
||||
} catch (cause: unknown) {
|
||||
@@ -41,6 +41,42 @@ export const readReferenceSourceVcs = async (
|
||||
}
|
||||
};
|
||||
|
||||
const resolveSourceHead = async (root: string): Promise<string> => {
|
||||
const dotgit = join(root, ".git");
|
||||
if (!(await lstat(dotgit)).isFile())
|
||||
return resolveRef({ fs, dir: root, ref: "HEAD" });
|
||||
const pointer = (await readFile(dotgit, "utf8")).replace(/\r?\n$/u, "");
|
||||
if (!pointer.startsWith("gitdir: ") || pointer.length === 8)
|
||||
throw new Error("Invalid Git directory pointer");
|
||||
const gitdir = resolve(root, pointer.slice(8));
|
||||
let commonDirectory: string;
|
||||
try {
|
||||
commonDirectory = resolve(
|
||||
gitdir,
|
||||
(await readFile(join(gitdir, "commondir"), "utf8")).replace(
|
||||
/\r?\n$/u,
|
||||
"",
|
||||
),
|
||||
);
|
||||
} catch (cause: unknown) {
|
||||
if (errorCode(cause) !== "ENOENT") throw cause;
|
||||
return resolveRef({ fs, dir: root, gitdir, ref: "HEAD" });
|
||||
}
|
||||
const head = (await readFile(join(gitdir, "HEAD"), "utf8")).trim();
|
||||
if (!head.startsWith("ref: "))
|
||||
return resolveRef({ fs, dir: root, gitdir, ref: "HEAD" });
|
||||
const ref = head.slice(5);
|
||||
const privateRef = ["refs/bisect/", "refs/rewritten/", "refs/worktree/"].some(
|
||||
(prefix) => ref.startsWith(prefix),
|
||||
);
|
||||
return resolveRef({
|
||||
fs,
|
||||
dir: root,
|
||||
gitdir: privateRef ? gitdir : commonDirectory,
|
||||
ref,
|
||||
});
|
||||
};
|
||||
|
||||
const errorCode = (cause: unknown): string | undefined =>
|
||||
typeof cause === "object" && cause !== null && "code" in cause
|
||||
? String(cause.code)
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { expect, it } from "vitest";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
import { execFileOutput } from "../../../src/process/ExecFileOutput.js";
|
||||
import { readReferenceSourceVcs } from "../../../src/application/ReferenceSourceVcsAdapter.js";
|
||||
|
||||
it("reads a linked worktree's own branch and detached HEAD through shared Git refs", async () => {
|
||||
const root = await createTestTempDirectory("rea-reference-worktree-");
|
||||
const repository = join(root, "repository");
|
||||
await mkdir(repository);
|
||||
const git = (...args: string[]) =>
|
||||
execFileOutput("git", args, { cwd: repository });
|
||||
await git("init", "--initial-branch=main");
|
||||
const commit = () =>
|
||||
git(
|
||||
"-c",
|
||||
"user.name=REA fixture",
|
||||
"-c",
|
||||
"user.email=fixture@example.invalid",
|
||||
"-c",
|
||||
"commit.gpgsign=false",
|
||||
"commit",
|
||||
"--allow-empty",
|
||||
"-m",
|
||||
"fixture",
|
||||
);
|
||||
await commit();
|
||||
const mainHead = (await git("rev-parse", "HEAD")).stdout.trim();
|
||||
const linked = join(root, "linked");
|
||||
await git("worktree", "add", "-b", "linked", linked);
|
||||
await execFileOutput(
|
||||
"git",
|
||||
[
|
||||
"-c",
|
||||
"user.name=REA fixture",
|
||||
"-c",
|
||||
"user.email=fixture@example.invalid",
|
||||
"-c",
|
||||
"commit.gpgsign=false",
|
||||
"commit",
|
||||
"--allow-empty",
|
||||
"-m",
|
||||
"linked fixture",
|
||||
],
|
||||
{ cwd: linked },
|
||||
);
|
||||
const linkedHead = (
|
||||
await execFileOutput("git", ["rev-parse", "HEAD"], { cwd: linked })
|
||||
).stdout.trim();
|
||||
expect(linkedHead).not.toBe(mainHead);
|
||||
expect(await readReferenceSourceVcs(repository)).toEqual({
|
||||
kind: "git",
|
||||
head: mainHead,
|
||||
dirty: null,
|
||||
});
|
||||
expect(await readReferenceSourceVcs(linked)).toEqual({
|
||||
kind: "git",
|
||||
head: linkedHead,
|
||||
dirty: null,
|
||||
});
|
||||
await git("pack-refs", "--all", "--prune");
|
||||
expect(await readReferenceSourceVcs(linked)).toEqual({
|
||||
kind: "git",
|
||||
head: linkedHead,
|
||||
dirty: null,
|
||||
});
|
||||
await execFileOutput("git", ["checkout", "--detach", mainHead], {
|
||||
cwd: linked,
|
||||
});
|
||||
expect(await readReferenceSourceVcs(linked)).toEqual({
|
||||
kind: "git",
|
||||
head: mainHead,
|
||||
dirty: null,
|
||||
});
|
||||
const relativePointer = join(root, "relative");
|
||||
await mkdir(relativePointer);
|
||||
await writeFile(
|
||||
join(relativePointer, ".git"),
|
||||
"gitdir: ../repository/.git\r\n",
|
||||
);
|
||||
expect(await readReferenceSourceVcs(relativePointer)).toEqual({
|
||||
kind: "git",
|
||||
head: mainHead,
|
||||
dirty: null,
|
||||
});
|
||||
const controller = new AbortController();
|
||||
controller.abort();
|
||||
expect(await readReferenceSourceVcs(linked, controller.signal)).toEqual({
|
||||
kind: "unknown",
|
||||
head: null,
|
||||
dirty: null,
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user