/** * ───────────────────────────────────────────── * SPB Git — Personal Git Platform * ───────────────────────────────────────────── * Author : Simon-Pierre Boucher * Contact : contact@spboucher.ai * File : cli/commands/clone.mjs * Purpose : `spbgit clone |--all` — clone into the workspace * License : MIT © Simon-Pierre Boucher * ───────────────────────────────────────────── */ import { existsSync, mkdirSync } from 'node:fs'; import { join, resolve } from 'node:path'; import pc from 'picocolors'; import { requireCliConfig } from '../lib/config.mjs'; import { api, EXIT } from '../lib/api.mjs'; import { git } from '../lib/git.mjs'; import { mapLimit, SYM } from '../lib/ui.mjs'; export function registerClone(program) { program .command('clone [name] [dir]') .description('clone a repository into the workspace (or a directory)') .option('--all', 'clone every server repo missing from the workspace', false) .action(async (name, dir, opts) => { const config = requireCliConfig(); mkdirSync(config.workspace, { recursive: true }); if (opts.all) { const { repos } = await api(config, 'GET', '/api/v1/repos', undefined, { auth: false }); const missing = repos.filter((r) => !existsSync(join(config.workspace, r.name))); if (missing.length === 0) { console.log(`${SYM.ok} Workspace already has every repository (${repos.length}).`); return; } let failures = 0; await mapLimit(missing, 4, async (repo) => { const dest = join(config.workspace, repo.name); const result = await git(config.workspace, ['clone', repo.cloneUrl, dest]); if (result.ok) console.log(`${SYM.ok} ${repo.name}`); else { failures += 1; console.error(`${SYM.fail} ${repo.name}: ${result.stderr.trim().split('\n').pop()}`); } }); console.log(`\nCloned ${missing.length - failures}/${missing.length} repositories into ${config.workspace}`); if (failures > 0) process.exit(EXIT.PARTIAL); return; } if (!name) { console.error(pc.red('✗ Provide a repository name or --all')); process.exit(EXIT.USER); } const dest = dir ? resolve(dir) : join(config.workspace, name); if (existsSync(dest)) { console.error(pc.red(`✗ Destination already exists: ${dest}`)); process.exit(EXIT.USER); } const url = `${config.server}/${name}.git`; const result = await git(process.cwd(), ['clone', url, dest]); if (!result.ok) { console.error(pc.red(`✗ Clone failed: ${result.stderr.trim().split('\n').pop()}`)); process.exit(EXIT.NETWORK); } console.log(`${SYM.ok} Cloned ${pc.bold(name)} → ${dest}`); }); }