rm

tcmts.cli.main.rm · #2i64xefu · term · runs on the server

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}`);
}

uses

used by