rm
uses tcmts.cli.files.linkingTo, which uses tcmts.cli.files.linkedName, which uses tcmts.cli.files.fileFormat, which uses node:path
Remove a name. One that something still named uses is refused (unless force): the things using it keep working,
but by hash. What's being removed with it (removing, the other names of one tcm rm) doesn't count as using it.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { linkingTo } from "#codebase/tcmts/cli/files"; import { confirm, UsageError } from "#codebase/tcmts/cli/ui"; export async function rm( cb: Codebase, name: string, force: boolean, removing: ReadonlySet<string> = new Set(), ) { const hs = cb.store.hashesAt(name); if (!hs.length) throw new UsageError(cb.notFound(name)); for (const h of hs) { const otherNames = cb.store.pathsOf(h).filter((p) => p !== name); // what uses it: code, and pages naming it (by hash), or linking to it if it's a file (by its name) const users = [ ...cb.store.dependents(h).filter((d) => cb.store.pathsOf(d).length), ...(cb.store.getDef(h)?.kind === "file" ? linkingTo(cb, name).flatMap((p) => cb.store.hashesAt(p)) : []), ].filter((u) => !cb.store.pathsOf(u).every((p) => removing.has(p))); if (users.length && !otherNames.length && !force) { const used = `'${name}' is used by ${users.map((u) => cb.displayRef(`#${u}`)).join(", ")}`; if (!(await confirm(`${used}. Remove the name anyway? (they keep working)`))) throw new UsageError(`${used}; pass --force to remove the name anyway (they keep working)`); } } cb.store.transaction(() => hs.forEach((h) => cb.store.removeName(name, h, `rm ${name}`))); cb.refreshShim(); console.log(`removed ${name}`); }