testBranchesSharePatches
Branches share patches: one made from another reads what that had through the same set, not a copy; what each records after is its own; a version coming back on one hides the patch out of it beneath, for that one alone; a merge's work set aside and put back is as it was; a deep stack of sets reads as a flat one; and a branch deleted takes the sets only it read.
import { PATCH_DEPTH } from "#codebase/tcmts/store"; import { open } from "#codebase/tcmts/store/test/history"; import assert from "node:assert/strict"; export const testBranchesSharePatches = () => { const h = (tag: string) => tag.padEnd(52, "z"); const [a, b, c, d, e, f] = ["a", "b", "c", "d", "e", "f"].map(h); const s = open(); const count = (table: string) => (s.db.prepare(`SELECT count(*) AS n FROM ${table}`).get() as { n: number }).n; s.addPatch(a!, b!); s.createBranch("side"); assert.equal(count("patches"), 1, "side reads main's patch, not a copy of it"); s.addPatch(b!, c!); s.switchBranch("side"); assert.equal(s.patched(a!), b, "side doesn't see main's later patch"); s.addPatch(b!, d!); assert.equal(s.patched(a!), d); s.switchBranch("main"); assert.equal(s.patched(a!), c); // a coming back on main: what replaced it then (in the set side shares) doesn't, on main s.addPatch(c!, a!); assert.equal(s.patched(a!), a); assert.equal(s.patched(b!), a); assert.deepEqual(s.patchesOf(), [ { old: b, new: c }, { old: c, new: a }, ]); s.switchBranch("side"); assert.equal(s.patched(a!), d); // a merge's work, set aside and put back const work = s.workOf("side"); s.addPatch(e!, f!); assert.equal(s.patched(e!), f); s.setWorkOf("side", work); assert.equal(s.patched(e!), e); assert.equal(s.patched(a!), d); // every branch made freezes another set; past PATCH_DEPTH of them, a branch reads a flat copy, the same s.switchBranch("main"); const made = Array.from( { length: PATCH_DEPTH + 3 }, (_, i) => [h(`m${i}a`), h(`m${i}b`)] as const, ); made.forEach(([o, n], i) => { s.addPatch(o, n); s.createBranch(`b${i}`); }); const depth = (branch: string) => ( s.db .prepare( "WITH RECURSIVE chain(id) AS (SELECT patches FROM branches WHERE name = ? UNION ALL SELECT s.base FROM patch_sets s JOIN chain ON s.id = chain.id WHERE s.base IS NOT NULL) SELECT count(*) AS n FROM chain", ) .get(branch) as { n: number } ).n; for (const branch of ["main", `b${made.length - 1}`]) { assert.ok(depth(branch) <= PATCH_DEPTH + 1, `${branch} reads through ${depth(branch)} sets`); s.switchBranch(branch); for (const [o, n] of made) assert.equal(s.patched(o), n); assert.equal(s.patched(a!), a); } // a branch deleted takes what only it read s.switchBranch("main"); const sets = count("patch_sets"); s.deleteBranch("side"); assert.ok(count("patch_sets") < sets, `${count("patch_sets")} < ${sets}`); assert.equal(s.patched(a!), a); }