spb/spbgit Public MIT
SPB Git — the platform hosting itself
JavaScript 73.9%
CSS 11.7%
Nunjucks 11.6%
Shell 2.7%
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