Julius MarmingeFix latest PR review findings832eb428 months agoHistory
243 lines · 8.6 KB · TypeScript
RawDownload
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";import fs from "node:fs";import os from "node:os";import path from "node:path"; import { describe, expect, it } from "vitest"; import { checkpointRefForThreadTurn, FilesystemCheckpointStore } from "./filesystemCheckpointStore";import { runProcess } from "./processRunner"; async function runGit(cwd: string, args: readonly string[]): Promise<string> {  const result = await runProcess("git", args, {    cwd,    allowNonZeroExit: true,  });  if (result.code !== 0) {    throw new Error(result.stderr.trim() || `git ${args.join(" ")} failed`);  }  return result.stdout.trim();} function exists(filePath: string): boolean {  return fs.existsSync(filePath);} async function createRepo(): Promise<string> {  const cwd = await mkdtemp(path.join(os.tmpdir(), "t3-fs-checkpoints-test-"));  await runGit(cwd, ["init", "--initial-branch=main"]);  await runGit(cwd, ["config", "user.email", "test@example.com"]);  await runGit(cwd, ["config", "user.name", "Test User"]);  await writeFile(path.join(cwd, "README.md"), "v1\n");  await writeFile(path.join(cwd, "tracked.txt"), "tracked-v1\n");  await runGit(cwd, ["add", "."]);  await runGit(cwd, ["commit", "-m", "Initial"]);  return cwd;} async function createRepoWithoutHead(): Promise<string> {  const cwd = await mkdtemp(path.join(os.tmpdir(), "t3-fs-checkpoints-empty-test-"));  await runGit(cwd, ["init", "--initial-branch=main"]);  return cwd;} describe("FilesystemCheckpointStore", () => {  it("captures refs without mutating branch history and restores workspace state", async () => {    const cwd = await createRepo();    const store = new FilesystemCheckpointStore();    const threadId = "thr_1";     try {      const headBefore = await runGit(cwd, ["rev-parse", "HEAD"]);       await store.captureCheckpoint({ cwd, threadId, turnCount: 0 });      const rootRef = checkpointRefForThreadTurn(threadId, 0);      const rootCommit = await runGit(cwd, ["rev-parse", "--verify", `${rootRef}^{commit}`]);      expect(rootCommit.length).toBeGreaterThan(0);      expect(await runGit(cwd, ["rev-parse", "HEAD"])).toBe(headBefore);       await writeFile(path.join(cwd, "README.md"), "v2\n");      await rm(path.join(cwd, "tracked.txt"));      await writeFile(path.join(cwd, "notes.md"), "notes\n");      await store.captureCheckpoint({ cwd, threadId, turnCount: 1 });       await writeFile(path.join(cwd, "README.md"), "v3\n");      await writeFile(path.join(cwd, "scratch.txt"), "scratch\n");      await writeFile(path.join(cwd, "tracked.txt"), "tracked-new\n");       const restoredRoot = await store.restoreCheckpoint({ cwd, threadId, turnCount: 0 });      expect(restoredRoot).toBe(true);      expect(await readFile(path.join(cwd, "README.md"), "utf8")).toBe("v1\n");      expect(await readFile(path.join(cwd, "tracked.txt"), "utf8")).toBe("tracked-v1\n");      expect(exists(path.join(cwd, "notes.md"))).toBe(false);      expect(exists(path.join(cwd, "scratch.txt"))).toBe(false);       const restoredTurn1 = await store.restoreCheckpoint({ cwd, threadId, turnCount: 1 });      expect(restoredTurn1).toBe(true);      expect(await readFile(path.join(cwd, "README.md"), "utf8")).toBe("v2\n");      expect(exists(path.join(cwd, "tracked.txt"))).toBe(false);      expect(await readFile(path.join(cwd, "notes.md"), "utf8")).toBe("notes\n");      expect(exists(path.join(cwd, "scratch.txt"))).toBe(false);    } finally {      await rm(cwd, { recursive: true, force: true });    }  });   it("returns false when restoring a missing checkpoint", async () => {    const cwd = await createRepo();    const store = new FilesystemCheckpointStore();     try {      const restored = await store.restoreCheckpoint({        cwd,        threadId: "thr_2",        turnCount: 999,      });      expect(restored).toBe(false);    } finally {      await rm(cwd, { recursive: true, force: true });    }  });   it("falls back to HEAD when restoring turn 0 and root checkpoint ref is missing", async () => {    const cwd = await createRepo();    const store = new FilesystemCheckpointStore();    const threadId = "thr_2b";     try {      await writeFile(path.join(cwd, "README.md"), "v2\n");      await store.captureCheckpoint({ cwd, threadId, turnCount: 1 });       await writeFile(path.join(cwd, "README.md"), "v3\n");      await writeFile(path.join(cwd, "scratch.txt"), "scratch\n");       const restored = await store.restoreCheckpoint({        cwd,        threadId,        turnCount: 0,      });       expect(restored).toBe(true);      expect(await readFile(path.join(cwd, "README.md"), "utf8")).toBe("v1\n");      expect(exists(path.join(cwd, "scratch.txt"))).toBe(false);    } finally {      await rm(cwd, { recursive: true, force: true });    }  });   it("prunes refs newer than the retained turn", async () => {    const cwd = await createRepo();    const store = new FilesystemCheckpointStore();    const threadId = "thr_3";     try {      await store.captureCheckpoint({ cwd, threadId, turnCount: 0 });      await writeFile(path.join(cwd, "README.md"), "turn1\n");      await store.captureCheckpoint({ cwd, threadId, turnCount: 1 });      await writeFile(path.join(cwd, "README.md"), "turn2\n");      await store.captureCheckpoint({ cwd, threadId, turnCount: 2 });       await store.pruneAfterTurn({        cwd,        threadId,        maxTurnCount: 1,      });       expect(await store.hasCheckpoint({ cwd, threadId, turnCount: 0 })).toBe(true);      expect(await store.hasCheckpoint({ cwd, threadId, turnCount: 1 })).toBe(true);      expect(await store.hasCheckpoint({ cwd, threadId, turnCount: 2 })).toBe(false);    } finally {      await rm(cwd, { recursive: true, force: true });    }  });   it("returns a unified patch between checkpoint turns", async () => {    const cwd = await createRepo();    const store = new FilesystemCheckpointStore();    const threadId = "thr_4";     try {      await store.captureCheckpoint({ cwd, threadId, turnCount: 0 });      await writeFile(path.join(cwd, "README.md"), "v2\n");      await writeFile(path.join(cwd, "new.txt"), "new file\n");      await store.captureCheckpoint({ cwd, threadId, turnCount: 1 });       const diff = await store.diffCheckpoints({        cwd,        threadId,        fromTurnCount: 0,        toTurnCount: 1,      });       expect(diff).toContain("diff --git a/README.md b/README.md");      expect(diff).toContain("diff --git a/new.txt b/new.txt");    } finally {      await rm(cwd, { recursive: true, force: true });    }  });   it("falls back to HEAD as diff base when turn 0 checkpoint is missing", async () => {    const cwd = await createRepo();    const store = new FilesystemCheckpointStore();    const threadId = "thr_5";     try {      await writeFile(path.join(cwd, "README.md"), "v2\n");      await writeFile(path.join(cwd, "new.txt"), "new file\n");      await store.captureCheckpoint({ cwd, threadId, turnCount: 1 });       const diff = await store.diffCheckpoints({        cwd,        threadId,        fromTurnCount: 0,        toTurnCount: 1,      });       expect(diff).toContain("diff --git a/README.md b/README.md");      expect(diff).toContain("diff --git a/new.txt b/new.txt");    } finally {      await rm(cwd, { recursive: true, force: true });    }  });   it("detects non-repo folders", async () => {    const cwd = await mkdtemp(path.join(os.tmpdir(), "t3-fs-checkpoints-nonrepo-"));    const store = new FilesystemCheckpointStore();     try {      expect(await store.isGitRepository(cwd)).toBe(false);    } finally {      await rm(cwd, { recursive: true, force: true });    }  });   it("returns false when repository path does not exist", async () => {    const store = new FilesystemCheckpointStore();    const cwd = path.join(os.tmpdir(), `t3-fs-checkpoints-missing-${Date.now()}`);     expect(await store.isGitRepository(cwd)).toBe(false);  });   it("restores checkpoint without reset when repository has no HEAD commit", async () => {    const cwd = await createRepoWithoutHead();    const store = new FilesystemCheckpointStore();    const threadId = "thr-no-head";     try {      await writeFile(path.join(cwd, "README.md"), "first\n");      await store.captureCheckpoint({ cwd, threadId, turnCount: 0 });       await writeFile(path.join(cwd, "README.md"), "second\n");      const restored = await store.restoreCheckpoint({        cwd,        threadId,        turnCount: 0,      });       expect(restored).toBe(true);      expect(await readFile(path.join(cwd, "README.md"), "utf8")).toBe("first\n");    } finally {      await rm(cwd, { recursive: true, force: true });    }  });});