import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { type GitRunner, readGitCheckout } from "./git-checkout.js"; describe("readGitCheckout", () => { const roots: string[] = []; afterEach(() => { for (const root of roots.splice(0)) { rmSync(root, { recursive: true, force: true }); } }); function tempDir(prefix: string) { const root = mkdtempSync(path.join(tmpdir(), prefix)); roots.push(root); return root; } it("returns absent status when .git is missing", async () => { const root = tempDir("git-checkout-absent-"); await expect(readGitCheckout(root)).resolves.toEqual({ present: false, remoteUrl: null, defaultBranch: null, headCommit: null, dirty: false, dirtyPaths: [], }); }); it("reads remote, branch, commit, and dirty paths from git metadata", async () => { const root = tempDir("git-checkout-present-"); mkdirSync(path.join(root, ".git")); writeFileSync(path.join(root, "README.md"), "hello"); const runner: GitRunner = async (args) => { if (args.join(" ") === "rev-parse HEAD") { return { ok: true, output: "abc123def456\n" }; } if (args.join(" ") === "rev-parse --abbrev-ref HEAD") { return { ok: true, output: "main\n" }; } if (args.join(" ") === "remote get-url origin") { return { ok: true, output: "https://github.com/example/demo.git\n" }; } if (args.includes("status")) { return { ok: true, output: " M README.md\n" }; } if (args.includes("ls-files")) { return { ok: true, output: "notes.txt\n" }; } return { ok: false, output: "" }; }; await expect(readGitCheckout(root, runner)).resolves.toEqual({ present: true, remoteUrl: "https://github.com/example/demo.git", defaultBranch: "main", headCommit: "abc123def456", dirty: true, dirtyPaths: ["README.md", "notes.txt"], }); }); });