kilo-loop/test/checkpoint.test.mjs
Vitali sharp8n 1eb9ec22c2 kilo loop
2026-09-13 19:29:03 +03:00

100 lines
4.2 KiB
JavaScript

import { test } from 'node:test'
import assert from 'node:assert/strict'
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { execFileSync } from 'node:child_process'
import { createCheckpoint, restoreCheckpoint, listCheckpoints, isGitRepo, dirtySubmodules } from '../src/checkpoint.mjs'
function git(project, args) {
return execFileSync('git', ['-c', 'user.email=t@t', '-c', 'user.name=t', ...args], { cwd: project, encoding: 'utf8' })
}
function tempRepo() {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'kilo-cp-'))
git(dir, ['init', '-q'])
fs.writeFileSync(path.join(dir, 'tracked.txt'), 'one\n')
git(dir, ['add', '.'])
git(dir, ['commit', '-qm', 'init'])
return dir
}
test('createCheckpoint captures a patch and untracked list', () => {
const project = tempRepo()
const runDir = path.join(project, 'run')
fs.appendFileSync(path.join(project, 'tracked.txt'), 'two\n')
fs.writeFileSync(path.join(project, 'new.txt'), 'untracked\n')
const cp = createCheckpoint(project, runDir, 'before iteration 1', { id: 'iter-01' })
assert.equal(cp.id, 'iter-01')
assert.ok(cp.patchBytes > 0)
assert.ok(cp.untracked.includes('new.txt'))
assert.ok(fs.existsSync(cp.patchFile))
assert.equal(listCheckpoints(runDir).length, 1)
})
test('restoreCheckpoint reverts tracked edits and removes new untracked files', () => {
const project = tempRepo()
const runDir = path.join(project, 'run')
const cp = createCheckpoint(project, runDir, 'before iteration 1', { id: 'iter-01' })
fs.writeFileSync(path.join(project, 'tracked.txt'), 'changed\n')
fs.writeFileSync(path.join(project, 'created-later.txt'), 'junk\n')
const res = restoreCheckpoint(project, cp)
assert.equal(res.ok, true)
assert.equal(fs.readFileSync(path.join(project, 'tracked.txt'), 'utf8'), 'one\n')
assert.equal(fs.existsSync(path.join(project, 'created-later.txt')), false)
})
test('restoreCheckpoint keeps untracked files that existed at checkpoint time', () => {
const project = tempRepo()
const runDir = path.join(project, 'run')
fs.writeFileSync(path.join(project, 'preexisting.txt'), 'keep me\n')
const cp = createCheckpoint(project, runDir, 'before iteration 1', { id: 'iter-01' })
fs.writeFileSync(path.join(project, 'later.txt'), 'junk\n')
restoreCheckpoint(project, cp)
assert.equal(fs.existsSync(path.join(project, 'preexisting.txt')), true)
assert.equal(fs.existsSync(path.join(project, 'later.txt')), false)
})
test('restoreCheckpoint reproduces pre-existing changes captured at checkpoint time', () => {
const project = tempRepo()
const runDir = path.join(project, 'run')
fs.writeFileSync(path.join(project, 'tracked.txt'), 'one\npreexisting\n')
const cp = createCheckpoint(project, runDir, 'before iteration 1', { id: 'iter-01' })
fs.writeFileSync(path.join(project, 'tracked.txt'), 'totally different\n')
const res = restoreCheckpoint(project, cp)
assert.equal(res.ok, true)
assert.equal(fs.readFileSync(path.join(project, 'tracked.txt'), 'utf8'), 'one\npreexisting\n')
})
test('checkpoint helpers are no-ops outside a git repository', () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'kilo-nogit-'))
assert.equal(isGitRepo(dir), false)
assert.equal(createCheckpoint(dir, path.join(dir, 'run'), 'x'), null)
})
test('restoreCheckpoint refuses to run when a submodule is dirty', () => {
const project = tempRepo()
const sub = path.join(project, 'sub')
fs.mkdirSync(sub)
git(sub, ['init', '-q'])
fs.writeFileSync(path.join(sub, 'x.txt'), 'a\n')
git(sub, ['add', '.'])
git(sub, ['commit', '-qm', 'sub init'])
fs.writeFileSync(
path.join(project, '.gitmodules'),
`[submodule "sub"]\n\tpath = sub\n\turl = ./sub\n`,
)
git(project, ['add', '.gitmodules'])
git(project, ['commit', '-qm', 'add submodule'])
// Dirty the submodule pointer by committing inside it and staging the pointer.
fs.appendFileSync(path.join(sub, 'x.txt'), 'b\n')
git(sub, ['commit', '-qam', 'sub change'])
git(project, ['add', 'sub'])
assert.deepEqual(dirtySubmodules(project), ['sub'])
const cp = createCheckpoint(project, path.join(project, 'run'), 'before iteration 1', { id: 'iter-01' })
const res = restoreCheckpoint(project, cp)
assert.equal(res.ok, false)
assert.match(res.error, /submodule/i)
})