import { assert, assertEquals, assertThrows } from "@std/assert"; import { expect } from "@std/expect"; import { describe, it } from "@std/testing/bdd"; import { commitSubjects, findCommitMessages, realGit, } from "../lib/view/commitmsg.ts"; import { git, initReftable, installHook, shellQuote, } from "./view-commitmsg-test-helpers.ts"; Deno.test("findCommitMessages: a SHA-256 repository's 64-character object id", () => { const sha = "a".repeat(64); const lines = [`commit ${sha}`, "Author: A B ", "", " Subject", ""]; const msgs = findCommitMessages(lines); assertEquals(msgs.length, 1); assertEquals(msgs[0].sha, sha); assertEquals([msgs[0].start, msgs[0].end], [3, 3]); }); Deno.test("commitSubjects: an email Subject wrapped over continuation lines", () => { const full = "0123456789abcdef0123456789abcdef01234567"; const subjects = commitSubjects([ `From ${full} Mon Sep 17 00:00:00 2001`, "From: A B ", "Date: Wed, 1 Jul 2026 12:00:00 -0700", "Subject: [PATCH v2 2/3] Rework the reconciliation path so that it", " no longer drops pending writes", "", "diff --git a/f b/f", ]); assertEquals( subjects.get(full), "Rework the reconciliation path so that it no longer drops pending writes", ); }); Deno.test({ name: "realGit: preserves whitespace in a relative core.hooksPath", ignore: Deno.build.os === "windows", async fn() { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); await git(root, ["commit", "-q", "--allow-empty", "-m", "original"]); const hooksName = " custom-hooks "; await git(root, ["config", "core.hooksPath", hooksName]); const hooks = `${root}/${hooksName}`; await Deno.mkdir(hooks); const marker = `${root}/post-commit-ran`; const hook = `${hooks}/post-commit`; await Deno.writeTextFile( hook, `#!/bin/sh\nprintf ran > ${shellQuote(marker)}\n`, ); await Deno.chmod(hook, 0o755); const runner = realGit(root); const original = runner.headSha(); assert(original, "repository has a HEAD commit"); runner.amendCommit("amended", new Map(), original); assertEquals(await Deno.readTextFile(marker), "ran"); } finally { await Deno.remove(root, { recursive: true }); } }, }); describe("realGit binary input", () => { it("rejects binary commit blobs before merging them as text", async () => { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); const nulPath = `${root}/payload.data`; const namedBinaryPath = `${root}/asset.png`; await Deno.writeFile( nulPath, new Uint8Array([98, 101, 102, 111, 114, 101, 10, 0, 97]), ); await Deno.writeTextFile(namedBinaryPath, "printable source text\n"); await git(root, ["add", "payload.data", "asset.png"]); await git(root, ["commit", "-q", "-m", "binary inputs"]); const runner = realGit(root); const head = runner.headSha(); assert(head, "repository has a HEAD commit"); expect(() => runner.fileAtCommit(head, nulPath)).toThrow( "Binary data is shown as a hex dump", ); expect(() => runner.fileAtCommit(head, namedBinaryPath)).toThrow( "Binary data is shown as a hex dump", ); expect(() => runner.amendCommit( null, new Map([[nulPath, "edited text\n"]]), head, ) ).toThrow("Binary data is shown as a hex dump"); expect(runner.headSha()).toBe(head); } finally { await Deno.remove(root, { recursive: true }); } }); it("preserves a UTF-8 BOM when amended text is re-encoded", async () => { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); const path = `${root}/value.ts`; await Deno.writeFile( path, new Uint8Array([ 0xef, 0xbb, 0xbf, ...new TextEncoder().encode("export const value = 1;\n"), ]), ); await git(root, ["add", "value.ts"]); await git(root, ["commit", "-q", "-m", "initial"]); const runner = realGit(root); const head = runner.headSha(); assert(head, "repository has a HEAD commit"); expect(runner.fileAtCommit(head, path)).toBe( "export const value = 1;\n", ); runner.amendCommit( null, new Map([[path, "export const value = 2;\n"]]), head, ); const shown = await new Deno.Command("git", { cwd: root, args: ["show", "HEAD:value.ts"], stdout: "piped", stderr: "piped", }).output(); assert(shown.success, new TextDecoder().decode(shown.stderr)); expect(shown.stdout).toEqual( new Uint8Array([ 0xef, 0xbb, 0xbf, ...new TextEncoder().encode("export const value = 2;\n"), ]), ); } finally { await Deno.remove(root, { recursive: true }); } }); }); Deno.test("realGit: amends reftable commits and preserves staged state", async () => { const root = await Deno.makeTempDir(); try { if (!await initReftable(root)) return; await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); await Deno.writeTextFile(`${root}/selected.txt`, "original selected\n"); await Deno.writeTextFile(`${root}/unrelated.txt`, "original unrelated\n"); await git(root, ["add", "selected.txt", "unrelated.txt"]); await git(root, ["commit", "-q", "-m", "original"]); const marker = `${root}/hook-ran`; await installHook(root, "pre-commit", `touch ${shellQuote(marker)}`); await Deno.writeTextFile(`${root}/selected.txt`, "amended selected\n"); await Deno.writeTextFile(`${root}/unrelated.txt`, "staged unrelated\n"); await git(root, ["add", "unrelated.txt"]); const runner = realGit(root); const head = runner.headSha(); assert(head, "repository has a HEAD commit"); const result = runner.amendCommit( "amended", new Map([[`${root}/selected.txt`, "amended selected\n"]]), head, ); assert(result.head !== head, "the reftable commit was replaced"); assertEquals(runner.headSha(), result.head); assertEquals( (await git(root, ["log", "-1", "--format=%s"])).trim(), "amended", ); assertEquals( await git(root, ["show", "HEAD:selected.txt"]), "amended selected\n", ); assertEquals( await git(root, ["show", "HEAD:unrelated.txt"]), "original unrelated\n", ); assertEquals( await git(root, ["show", ":unrelated.txt"]), "staged unrelated\n", ); await Deno.stat(marker); } finally { await Deno.remove(root, { recursive: true }); } }); Deno.test("realGit: preserves pager insertion order around a workspace insertion", async () => { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); const runner = realGit(root); assert(runner.applyFileChanges, "the real Git runner applies file changes"); assertEquals( runner.applyFileChanges( "A\nB\n", "A\nX\nB\n", "A\nP\nX\nQ\nB\n", `${root}/f.txt`, ), "A\nP\nQ\nB\n", ); } finally { await Deno.remove(root, { recursive: true }); } }); Deno.test("realGit: reads and writes selected files through clean filters", async () => { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); await git(root, ["config", "filter.caps.clean", "tr a-z A-Z"]); await git(root, ["config", "filter.caps.smudge", "tr A-Z a-z"]); await Deno.writeTextFile(`${root}/.gitattributes`, "*.dat filter=caps\n"); const path = `${root}/f.dat`; await Deno.writeTextFile(path, "original\n"); await git(root, ["add", ".gitattributes", "f.dat"]); await git(root, ["commit", "-q", "-m", "original"]); const runner = realGit(root); const head = runner.headSha(); assert(head, "repository has a HEAD commit"); assertEquals(runner.fileAtCommit(head, path), "original\n"); runner.amendCommit("amended", new Map([[path, "pager\n"]]), head); assertEquals(await git(root, ["show", "HEAD:f.dat"]), "PAGER\n"); assertEquals(await git(root, ["show", ":f.dat"]), "PAGER\n"); } finally { await Deno.remove(root, { recursive: true }); } }); Deno.test({ name: "realGit: rolls back a nested commit made by a post-commit hook", ignore: Deno.build.os === "windows", async fn() { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); await Deno.writeTextFile(`${root}/f.txt`, "original\n"); await git(root, ["add", "f.txt"]); await git(root, ["commit", "-q", "-m", "original"]); const runner = realGit(root); const head = runner.headSha(); assert(head, "repository has a HEAD commit"); const marker = `${root}/.git/nested-hook-ran`; await installHook( root, "post-commit", `if test ! -e ${shellQuote(marker)}; then touch ${shellQuote(marker)} git commit --allow-empty -q -m nested fi`, ); let error = ""; try { runner.amendCommit("amended", new Map(), head); } catch (caught) { error = caught instanceof Error ? caught.message : String(caught); } assert(error.includes("HEAD changed"), error || "the amend did not fail"); assertEquals(runner.headSha(), head); assertEquals( (await git(root, ["rev-list", "--count", "HEAD"])).trim(), "1", ); } finally { await Deno.remove(root, { recursive: true }); } }, }); Deno.test("realGit: rejects a stale expected HEAD", async () => { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); await git(root, ["commit", "-q", "--allow-empty", "-m", "original"]); const runner = realGit(root); const head = runner.headSha(); assert(head, "repository has a HEAD commit"); assertThrows( () => runner.amendCommit("amended", new Map(), "0".repeat(head.length)), Error, "HEAD moved before", ); assertEquals(runner.headSha(), head); } finally { await Deno.remove(root, { recursive: true }); } }); Deno.test({ name: "realGit: rejects two journal claims for the amended commit", ignore: Deno.build.os === "windows", async fn() { const root = await Deno.makeTempDir(); try { await git(root, ["init", "-q"]); await git(root, ["config", "user.email", "t@t.test"]); await git(root, ["config", "user.name", "Test"]); await git(root, ["commit", "-q", "--allow-empty", "-m", "original"]); await installHook( root, "reference-transaction", `if test "\${1-}" = committed; then read old object ref if test "$old" != 0000000000000000000000000000000000000000 && test "$object" != 0000000000000000000000000000000000000000; then printf '%s %s %s\n%s %s %s\n' "$old" "$object" refs/heads/claim-a "$old" "$object" refs/heads/claim-b > "$(dirname "$GIT_INDEX_FILE")/reference-transactions" fi fi`, ); const runner = realGit(root); const head = runner.headSha(); assert(head, "repository has a HEAD commit"); assertThrows( () => runner.amendCommit("amended", new Map(), head), Error, "more than one possible amended commit", ); assert( runner.headSha() !== head, "ambiguous ownership leaves the new ref untouched", ); } finally { await Deno.remove(root, { recursive: true }); } }, });