mirror of
https://github.com/cline/cline.git
synced 2026-10-29 17:42:34 +08:00
fix(core): pick up checkpoints when git is initialized mid-session (#13026)
ensureGitRepository cached a negative probe for the lifetime of the hook instance, so a session started in a non-git folder never got checkpoints even after the user ran git init. Cache only the positive answer and re-probe otherwise; the probe runs at most once per user turn.
This commit is contained in:
@@ -341,6 +341,47 @@ describe("createCheckpointHooks", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("starts checkpointing after the user runs git init mid-session", async () => {
|
||||
const cwd = await mkdtemp(join(tmpdir(), "core-checkpoint-nogit-"));
|
||||
let metadata: Record<string, unknown> | undefined;
|
||||
try {
|
||||
const hooks = createCheckpointHooks({
|
||||
cwd,
|
||||
sessionId: "sess_git_init_later",
|
||||
readSessionMetadata: async () => metadata,
|
||||
writeSessionMetadata: async (next) => {
|
||||
metadata = next;
|
||||
},
|
||||
});
|
||||
|
||||
// First turn: no git repo yet, so no checkpoint is written.
|
||||
await writeFile(join(cwd, "note.txt"), "before-init\n", "utf8");
|
||||
await runCheckpointHooks(hooks);
|
||||
expect(metadata?.checkpoint).toBeUndefined();
|
||||
|
||||
// The user initializes git mid-session.
|
||||
await runGit(cwd, "init");
|
||||
await runGit(cwd, "config", "user.name", "Codex Test");
|
||||
await runGit(cwd, "config", "user.email", "codex@example.com");
|
||||
await runGit(cwd, "add", "note.txt");
|
||||
await runGit(cwd, "commit", "-m", "initial");
|
||||
|
||||
// Next turn on the same hook instance picks up the new repo and
|
||||
// checkpoints from here forward.
|
||||
await writeFile(join(cwd, "note.txt"), "after-init\n", "utf8");
|
||||
await runCheckpointHooks(hooks, {
|
||||
messages: [userMessage("first request"), userMessage("second request")],
|
||||
});
|
||||
|
||||
const checkpoint = metadata?.checkpoint as CheckpointMetadata;
|
||||
expect(checkpoint.history).toHaveLength(1);
|
||||
expect(checkpoint.latest.runCount).toBe(2);
|
||||
expect(checkpoint.latest.kind).toBe("stash");
|
||||
} finally {
|
||||
await rm(cwd, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("skips checkpoint creation for subagents", async () => {
|
||||
const cwd = await createGitRepo();
|
||||
let writes = 0;
|
||||
|
||||
@@ -321,8 +321,12 @@ export function createCheckpointHooks(
|
||||
let rootRunMessageStart: number | undefined;
|
||||
|
||||
const ensureGitRepository = async (): Promise<boolean> => {
|
||||
if (repoSupported !== undefined) {
|
||||
return repoSupported;
|
||||
// Only cache the positive answer: a cwd that is not a git repo can
|
||||
// become one mid-session (the user runs `git init`), and this probe
|
||||
// fires at most once per user turn, so re-checking is cheap. Once the
|
||||
// repo is detected, checkpoints start applying from that turn onward.
|
||||
if (repoSupported === true) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
const result = await runGit(options.cwd, [
|
||||
|
||||
Reference in New Issue
Block a user