|
1 | | -import { describe, test, expect } from "bun:test"; |
| 1 | +import { afterEach, describe, expect, spyOn, test } from "bun:test"; |
2 | 2 | import fs from "node:fs"; |
3 | 3 | import os from "node:os"; |
4 | 4 | import path from "node:path"; |
@@ -446,3 +446,68 @@ describe("createOptimizedContextStore checkpoint", () => { |
446 | 446 | expect(atHead).toHaveLength(total); |
447 | 447 | }, 20_000); |
448 | 448 | }); |
| 449 | + |
| 450 | +describe("createOptimizedContextStore without native git", () => { |
| 451 | + const originalWhich = Bun.which.bind(Bun); |
| 452 | + let whichSpy: ReturnType<typeof spyOn> | undefined; |
| 453 | + let spawnSpy: ReturnType<typeof spyOn> | undefined; |
| 454 | + |
| 455 | + afterEach(() => { |
| 456 | + whichSpy?.mockRestore(); |
| 457 | + spawnSpy?.mockRestore(); |
| 458 | + whichSpy = undefined; |
| 459 | + spawnSpy = undefined; |
| 460 | + }); |
| 461 | + |
| 462 | + test("returns the base isogit store and commits without spawning git", async () => { |
| 463 | + whichSpy = spyOn(Bun, "which").mockImplementation((cmd: string) => { |
| 464 | + if (cmd === "git") return null; |
| 465 | + return originalWhich(cmd); |
| 466 | + }); |
| 467 | + spawnSpy = spyOn(Bun, "spawn"); |
| 468 | + |
| 469 | + const dir = tempDir(); |
| 470 | + const store = await createOptimizedContextStore(dir); |
| 471 | + |
| 472 | + await store.writeTurns([turn("no-git")]); |
| 473 | + await store.writeMetadata({ |
| 474 | + pendingOperations: [], |
| 475 | + tokenUsage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, thinking: 0 }, |
| 476 | + }); |
| 477 | + const commit = await store.commit({ message: "isogit fallback" }); |
| 478 | + |
| 479 | + expect(commit.hash.length).toBeGreaterThan(0); |
| 480 | + expect(commit.message).toBe("isogit fallback"); |
| 481 | + |
| 482 | + const loaded = await store.load(); |
| 483 | + expect(loaded.turns).toHaveLength(1); |
| 484 | + expect((loaded.turns[0]!.content[0] as { text: string }).text).toBe("no-git"); |
| 485 | + |
| 486 | + const gitSpawns = spawnSpy.mock.calls.filter((call: unknown[]) => { |
| 487 | + const argv = call[0]; |
| 488 | + return Array.isArray(argv) && argv[0] === "git"; |
| 489 | + }); |
| 490 | + expect(gitSpawns).toHaveLength(0); |
| 491 | + }); |
| 492 | + |
| 493 | + test("still wraps with native git when git is on PATH", async () => { |
| 494 | + expect(originalWhich("git")).not.toBeNull(); |
| 495 | + |
| 496 | + const dir = tempDir(); |
| 497 | + const store = await createOptimizedContextStore(dir); |
| 498 | + spawnSpy = spyOn(Bun, "spawn"); |
| 499 | + |
| 500 | + await store.writeTurns([turn("with-git")]); |
| 501 | + await store.writeMetadata({ |
| 502 | + pendingOperations: [], |
| 503 | + tokenUsage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, thinking: 0 }, |
| 504 | + }); |
| 505 | + await store.commit({ message: "native path" }); |
| 506 | + |
| 507 | + const gitSpawns = spawnSpy.mock.calls.filter((call: unknown[]) => { |
| 508 | + const argv = call[0]; |
| 509 | + return Array.isArray(argv) && argv[0] === "git"; |
| 510 | + }); |
| 511 | + expect(gitSpawns.length).toBeGreaterThan(0); |
| 512 | + }); |
| 513 | +}); |
0 commit comments