apply
uses tcmts.cli.style.dim, which uses node:util
Store the analyzed definitions and move names: add only binds free names, update also replaces.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { checkDocExamples } from "#codebase/tcmts/cli/docs"; import { checkStoredRows, printDependents, printRows, STATUS_LABEL, textChanged } from "#codebase/tcmts/cli/main"; import type { Row, Status } from "#codebase/tcmts/cli/main"; import { forgetConflict } from "#codebase/tcmts/cli/merge"; import { bold, dim, red, yellow } from "#codebase/tcmts/cli/style"; import { shortHash } from "#codebase/tcmts/core/hash"; export function apply( cb: Codebase, rows: Row[], mode: "add" | "update", command: string, quiet: boolean, ): boolean { // (what already used a version nothing names: only what this leaves so is said, below; by name, as a definition // re-derived for another change can still use it, and isn't left so by this) const staleBefore = new Set(cb.store.unnamedUses().map((u) => `${u.path} ${u.uses}`)); cb.putDefs(rows.map((r) => r.def)); const patches = new Map<string, string>(); const skipped: Row[] = []; cb.store.transaction(() => { for (const r of rows) { if (r.status === "new" || r.status === "alias") { cb.store.addName(r.path, r.def.hash, r.def.kind, command); // (code stored before, written differently now: it reads as it's written) if (textChanged(cb, r.def)) cb.store.setText(r.def, command); } // the same code with another doc, or written differently: on this branch it reads as it's written now (its // hash, and every other branch, untouched), a change in the branch's history like any else if (r.status === "doc" || r.status === "text") cb.store.setText(r.def, command); else if (r.status === "update" || r.status === "conflict") { if (mode === "add") { skipped.push(r); continue; } const olds = cb.store.hashesAt(r.path, r.def.kind); // (saved over a conflict, it's what the name holds now: the conflict is resolved, once) if (r.status === "conflict") forgetConflict(cb, r.path, r.def.kind); for (const old of olds) { patches.set(old, r.def.hash); cb.store.addPatch(old, r.def.hash); cb.store.clearTodo(old); } cb.store.replaceNames(r.path, olds, r.def.hash, r.def.kind, command); if (textChanged(cb, r.def)) cb.store.setText(r.def, command); } } }); if (quiet) { const counts = new Map<Status, number>(); for (const r of rows) if (!skipped.includes(r)) counts.set(r.status, (counts.get(r.status) ?? 0) + 1); console.log( [...counts].map(([s, n]) => `${STATUS_LABEL[s].trim()} ${n}`).join(dim(" · ")) || dim("nothing to do"), ); } else printRows( rows.filter((r) => !skipped.includes(r)), (d) => cb.store.shownSignature(d), ); for (const r of skipped) console.log( `${yellow(" ~ skipped ")} ${bold(r.path)} ${dim("already names a different definition; use `tcm update`")}`, ); checkStoredRows( cb, rows.map((r) => r.def), ); 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\``), ); } // a definition this left using a version nothing names (re-derived against one that was itself replaced) is wrong, // and said now rather than found later // (one that couldn't follow is to do: `tcm todo` says so) const toDo = new Set(cb.store.todos().map((t) => t.hash)); const stale = cb.store .unnamedUses() .filter((u) => !staleBefore.has(`${u.path} ${u.uses}`) && !toDo.has(u.hash)); for (const u of stale) console.log( red( ` ! ${u.path} now uses a version of ${u.madeAs} nothing names (${shortHash(u.uses)}): \`tcm edit ${u.path}\` and \`tcm update\` point it at the current one (and please report this)`, ), ); cb.refreshShim(); // examples in docs are code too: the ones just saved, and the ones naming anything just replaced, must still // typecheck (an import's library docs are prose for readers, so they're left alone) if (!quiet) for (const p of checkDocExamples( cb, rows.map((r) => r.def.hash), )) console.log(yellow(` ! ${p}`)); return skipped.length === 0; }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.docs.checkDocExamples
- tcmts.cli.main.Row
- tcmts.cli.main.STATUS_LABEL
- tcmts.cli.main.Status
- tcmts.cli.main.checkStoredRows
- tcmts.cli.main.printDependents
- tcmts.cli.main.printRows
- tcmts.cli.main.textChanged
- tcmts.cli.merge.forgetConflict
- tcmts.cli.style.bold
- tcmts.cli.style.dim
- tcmts.cli.style.red
- tcmts.cli.style.yellow
- tcmts.core.hash.shortHash