resolveConflict

tcmts.cli.main.resolveConflict · #m24s4z6f · term · runs on the server

uses tcmts.cli.main.printDependents, which uses process

Settle a conflict by keeping one of the definitions a name holds. The others are replaced by it, as an update replaces: what was derived from them (code that used them, re-derived against them by a merge) is re-derived against the one kept.

import type { Codebase } from "#codebase/tcmts/cli/codebase";
import { printDependents } from "#codebase/tcmts/cli/main";
import { conflictAt, forgetConflict } from "#codebase/tcmts/cli/merge";
import { red } from "#codebase/tcmts/cli/style";
import { UsageError } from "#codebase/tcmts/cli/ui";
import { shortHash } from "#codebase/tcmts/core/hash";

export function resolveConflict(cb: Codebase, name: string, keep: string) {
  const k = cb.lookupOne(keep);
  const hs = cb.store.hashesAt(name, cb.store.getDef(k)!.kind);
  if (!hs.includes(k)) throw new UsageError(`${keep} is not one of the definitions named ${name}`);
  const patches = new Map<string, string>();
  // (named by the side kept, where it's known)
  const side = conflictAt(cb, name, cb.store.getDef(k)!.kind)?.sides.find(
    (s) => s.hash === k,
  )?.side;
  const command = `resolve ${name} (${side ?? `#${shortHash(k)}`})`;
  forgetConflict(cb, name, cb.store.getDef(k)!.kind);
  cb.store.transaction(() => {
    for (const h of hs)
      if (h !== k) {
        cb.store.removeName(name, h, command);
        cb.store.addPatch(h, k);
        cb.store.clearTodo(h);
        patches.set(h, k);
      }
  });
  console.log(`${name} → ${shortHash(k)}`);
  if (patches.size) {
    const { updated, failed } = cb.propagate(patches);
    printDependents(updated);
    if (failed.length)
      console.log(
        red(`\n  ${failed.length} dependent definition(s) no longer typecheck; see \`tcm todo\``),
      );
  }
  cb.refreshShim();
}

uses

used by