historySides

tcmts.share.historySides · #udail4bi · term · runs anywhere

What each of a branch's entries (newest first, as historyList reads them) is beside main: its own work, on the branch and not on main (own); landed on main, a squashed landing (merge <branch> on main) taking it, said by that landing, the branch having merged it back since (landed); or main's, in main's history (base). For main itself, or a codebase without one, there's no base, and nothing is said.

import type { HistoryItem } from "#codebase/tcmts/cli/changes";
import type { Codebase } from "#codebase/tcmts/cli/codebase";

export function historySides(
  cb: Codebase,
  branch: string,
  entries: HistoryItem[],
): { base?: string; sides: Map<string, { side: "own" | "landed" | "base"; landing?: string }> } {
  const sides = new Map<string, { side: "own" | "landed" | "base"; landing?: string }>();
  const base = branch !== "main" && cb.store.hasBranch("main") ? "main" : undefined;
  if (!base) return { sides };
  const onBase = new Set(cb.store.ancestors(cb.store.head(base)));
  const landing = (h: string) =>
    onBase.has(h) && cb.store.causal(h)?.command.split("\n")[0] === `merge ${branch}`;
  // (newest first: a merge back of a landing, and every entry before it, landed with it)
  let landed: string | undefined;
  for (const e of entries) {
    if (onBase.has(e.hash)) {
      sides.set(e.hash, { side: "base" });
      continue;
    }
    const back = e.parents.find(landing);
    if (back) landed = back;
    sides.set(e.hash, landed ? { side: "landed", landing: landed } : { side: "own" });
  }
  return { base, sides };
}

uses

used by