mergeTexts

tcmts.cli.merge.mergeTexts · #gkse6qax · term · runs anywhere

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] };
}

uses

used by