SPB Git

spb/spbgit Public MIT

SPB Git — the platform hosting itself

JavaScript 73.9% CSS 11.7% Nunjucks 11.6% Shell 2.7%
3.0 KB · 70 lines javascript
Raw Blame History
1/**2 * ─────────────────────────────────────────────3 *  SPB Git — Personal Git Platform4 * ─────────────────────────────────────────────5 *  Author  : Simon-Pierre Boucher6 *  Contact : contact@spboucher.ai7 *  File    : cli/commands/clone.mjs8 *  Purpose : `spbgit clone <name>|--all` — clone into the workspace9 *  License : MIT © Simon-Pierre Boucher10 * ─────────────────────────────────────────────11 */1213import { existsSync, mkdirSync } from 'node:fs';14import { join, resolve } from 'node:path';15import pc from 'picocolors';16import { requireCliConfig } from '../lib/config.mjs';17import { api, EXIT } from '../lib/api.mjs';18import { git } from '../lib/git.mjs';19import { mapLimit, SYM } from '../lib/ui.mjs';2021export function registerClone(program) {22  program23    .command('clone [name] [dir]')24    .description('clone a repository into the workspace (or a directory)')25    .option('--all', 'clone every server repo missing from the workspace', false)26    .action(async (name, dir, opts) => {27      const config = requireCliConfig();28      mkdirSync(config.workspace, { recursive: true });2930      if (opts.all) {31        const { repos } = await api(config, 'GET', '/api/v1/repos', undefined, { auth: false });32        const missing = repos.filter((r) => !existsSync(join(config.workspace, r.name)));33        if (missing.length === 0) {34          console.log(`${SYM.ok} Workspace already has every repository (${repos.length}).`);35          return;36        }37        let failures = 0;38        await mapLimit(missing, 4, async (repo) => {39          const dest = join(config.workspace, repo.name);40          const result = await git(config.workspace, ['clone', repo.cloneUrl, dest]);41          if (result.ok) console.log(`${SYM.ok} ${repo.name}`);42          else {43            failures += 1;44            console.error(`${SYM.fail} ${repo.name}: ${result.stderr.trim().split('\n').pop()}`);45          }46        });47        console.log(`\nCloned ${missing.length - failures}/${missing.length} repositories into ${config.workspace}`);48        if (failures > 0) process.exit(EXIT.PARTIAL);49        return;50      }5152      if (!name) {53        console.error(pc.red('✗ Provide a repository name or --all'));54        process.exit(EXIT.USER);55      }56      const dest = dir ? resolve(dir) : join(config.workspace, name);57      if (existsSync(dest)) {58        console.error(pc.red(`✗ Destination already exists: ${dest}`));59        process.exit(EXIT.USER);60      }61      const url = `${config.server}/${name}.git`;62      const result = await git(process.cwd(), ['clone', url, dest]);63      if (!result.ok) {64        console.error(pc.red(`✗ Clone failed: ${result.stderr.trim().split('\n').pop()}`));65        process.exit(EXIT.NETWORK);66      }67      console.log(`${SYM.ok} Cloned ${pc.bold(name)} → ${dest}`);68    });69}70