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/create.mjs8 * Purpose : `spbgit create` — create on server, optionally push cwd9 * License : MIT © Simon-Pierre Boucher10 * ─────────────────────────────────────────────11 */1213import { existsSync } from 'node:fs';14import { join } 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';1920export function registerCreate(program) {21 program22 .command('create <name>')23 .description('create a repository on the server')24 .option('-d, --description <desc>', 'repository description', '')25 .option('--topics <topics>', 'comma-separated topics (max 10)')26 .option('--pinned', 'pin on the home page', false)27 .option('--push', 'also init the current directory, add remote, commit and push', false)28 .action(async (name, opts) => {29 const config = requireCliConfig();30 const topics = (opts.topics ?? '')31 .split(',')32 .map((t) => t.trim().toLowerCase())33 .filter(Boolean)34 .slice(0, 10);35 const repo = await api(config, 'POST', '/api/v1/repos', {36 name,37 description: opts.description,38 topics,39 pinned: Boolean(opts.pinned),40 });41 console.log(`${pc.green('✓')} Created ${pc.bold(repo.name)} → ${repo.url}`);4243 if (!opts.push) return;44 const cwd = process.cwd();45 if (!existsSync(join(cwd, '.git'))) {46 const init = await git(cwd, ['init', '-b', 'main']);47 if (!init.ok) {48 console.error(pc.red(`✗ git init failed: ${init.stderr}`));49 process.exit(EXIT.USER);50 }51 console.log(`${pc.green('✓')} Initialized git repository in ${cwd}`);52 }53 const hasRemote = await git(cwd, ['remote', 'get-url', 'origin']);54 if (!hasRemote.ok) {55 await git(cwd, ['remote', 'add', 'origin', repo.cloneUrl]);56 console.log(`${pc.green('✓')} Remote origin → ${repo.cloneUrl}`);57 }58 const hasCommit = await git(cwd, ['rev-parse', '--verify', 'HEAD']);59 if (!hasCommit.ok) {60 await git(cwd, ['add', '-A']);61 const commit = await git(cwd, ['commit', '-m', 'feat: initial commit']);62 if (!commit.ok) {63 console.error(pc.red(`✗ Nothing to commit — add files first, then: git push -u origin main`));64 process.exit(EXIT.USER);65 }66 console.log(`${pc.green('✓')} Initial commit created`);67 }68 const branch = (await git(cwd, ['rev-parse', '--abbrev-ref', 'HEAD'])).stdout.trim() || 'main';69 const push = await git(cwd, ['push', '-u', 'origin', branch], { token: config.token });70 if (!push.ok) {71 console.error(pc.red(`✗ Push failed: ${push.stderr.trim()}`));72 process.exit(EXIT.NETWORK);73 }74 console.log(`${pc.green('✓')} Pushed ${branch} — live at ${repo.url}`);75 });76}77