needsFixing

tcmts.cli.codebase.needsFixing · #2e3vb4ri · term · runs anywhere

What needs fixing on this branch, worked out rather than taken from what was recorded: a definition that couldn't follow a change (its record, Store.todos, says why) needs fixing only while it's named and still uses a version something newer replaced, or uses another that needs fixing. So nothing's left over when a branch goes back to what it was (tcm reset, a merge undone), however the records got there.

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

export function needsFixing(cb: Codebase): { hash: string; message: string }[] {
  const recorded = cb.store.todos();
  if (!recorded.length) return [];
  const live = cb.liveHashes();
  const named = new Set(cb.store.names(undefined, true).map((r) => r.hash));
  const why = new Map(
    recorded.filter((t) => live.has(t.hash) && named.has(t.hash)).map((t) => [t.hash, t]),
  );
  const uses = (h: string) =>
    (cb.store.getDef(h)?.deps ?? [])
      .filter((d) => d.ref.startsWith("#"))
      .map((d) => d.ref.slice(1));
  // (a version something newer replaced: not named, and patched to what replaced it)
  const behind = (h: string) => !named.has(h) && cb.store.patched(h) !== h;
  const broken = new Set([...why.keys()].filter((h) => uses(h).some(behind)));
  for (let grew = true; grew;) {
    grew = false;
    for (const h of why.keys())
      if (!broken.has(h) && uses(h).some((u) => broken.has(u))) {
        broken.add(h);
        grew = true;
      }
  }
  return [...broken].map((h) => why.get(h)!);
}

uses

used by