runClone

tcmts.cli.run.runClone · #o5iuzfoo · function · runs on the server

uses node:path

Runs tcm clone: tcm init in a new directory, the remote added as origin, and its main branch pulled. A clone that fails leaves no directory behind.

import { Codebase } from "#codebase/tcmts/cli/codebase";
import { routeClone } from "#codebase/tcmts/cli/commands";
import { execute } from "#codebase/tcmts/cli/main";
import { cloneDirectory } from "#codebase/tcmts/cli/run";
import type { Started } from "#codebase/tcmts/cli/run";
import { dim } from "#codebase/tcmts/cli/style";
import { addRemote, pull, remoteLocation } from "#codebase/tcmts/cli/sync";
import { success, UsageError } from "#codebase/tcmts/cli/ui";
import { parse } from "@bomb.sh/router";
import fs from "node:fs";
import path_1 from "node:path";

export async function runClone({ cmd, rest, cwd }: Started): Promise<number> {
  const { model } = execute(cmd, parse(routeClone(), { argv: rest }));
  const url = remoteLocation(model.url);
  const typed = model.dir ?? cloneDirectory(url);
  const dir = path_1.resolve(cwd, typed);
  if (fs.existsSync(dir) && fs.readdirSync(dir).length)
    throw new UsageError(
      `${typed} is there already and isn't empty: clone into a new directory (\`tcm clone ${model.url} <dir>\`)`,
    );
  const made = !fs.existsSync(dir);
  fs.mkdirSync(dir, { recursive: true });
  try {
    const cb = Codebase.init(dir);
    addRemote(cb, "origin", url, model.token, model.fingerprint);
    console.log(dim(`cloning ${url} into ${typed}`));
    await pull(cb, "origin", undefined);
  } catch (e) {
    // (it was new, or empty: what's in it now is the clone's)
    if (made) fs.rmSync(dir, { recursive: true, force: true });
    else
      for (const f of fs.readdirSync(dir))
        fs.rmSync(path_1.join(dir, f), { recursive: true, force: true });
    throw e;
  }
  success(`cloned into ${typed}: \`cd ${typed}\`, then \`tcm\` (or \`tcm studio\`)`);
  return 0;
}

uses

used by