mergeTexts
The text versions a merge leaves each merged definition showing (its comments, layout and doc, which aren't in its
hash), three-way as names are: a side that changed a definition's text keeps that change. conflicts: changed by
both, differently (ours is kept). lost: changed by one side, whose definition the merge doesn't keep (the other
side changed its code, or deleted it).
import type { NameState } from "#codebase/tcmts/cli/diff"; export function mergeTexts( base: ReadonlyMap<string, string>, ours: ReadonlyMap<string, string>, theirs: ReadonlyMap<string, string>, states: { ours: NameState; theirs: NameState; merged: NameState }, ): { texts: Map<string, string>; conflicts: string[]; lost: string[] } { const hashes = (s: NameState) => new Set([...s.values()].flatMap((hs) => [...hs])); const kept = hashes(states.merged); const texts = new Map<string, string>(); const conflicts: string[] = []; for (const h of kept) { const [b, o, t] = [base.get(h), ours.get(h), theirs.get(h)]; const r = o === t || t === b ? o : o === b ? t : (conflicts.push(h), o); if (r) texts.set(h, r); } const lost = new Set<string>(); for (const [side, named] of [ [ours, hashes(states.ours)], [theirs, hashes(states.theirs)], ] as const) for (const h of named) if (!kept.has(h) && side.get(h) !== base.get(h)) lost.add(h); return { texts, conflicts, lost: [...lost] }; }