/** * ───────────────────────────────────────────── * SPB Git — Personal Git Platform * ───────────────────────────────────────────── * Author : Simon-Pierre Boucher * Contact : contact@spboucher.ai * File : cli/commands/push.mjs * Purpose : `spbgit push [name]|--all` — push current branches * License : MIT © Simon-Pierre Boucher * ───────────────────────────────────────────── */ import { basename } from 'node:path'; import pc from 'picocolors'; import { requireCliConfig } from '../lib/config.mjs'; import { git, repoStatus } from '../lib/git.mjs'; import { mapLimit, SYM } from '../lib/ui.mjs'; import { EXIT } from '../lib/api.mjs'; import { resolveTargets } from './commit.mjs'; export function registerPush(program) { program .command('push [name]') .description('push the current branch of target repo(s)') .option('--all', 'every workspace repo with commits ahead', false) .action(async (name, opts) => { const config = requireCliConfig(); const targets = resolveTargets(config, name, opts.all); let failures = 0; let pushed = 0; await mapLimit(targets, 4, async (dir) => { const repo = basename(dir); const status = await repoStatus(dir); if (opts.all && status.hasUpstream && status.ahead === 0) { console.log(`${SYM.skip} ${repo} ${pc.dim('nothing to push')}`); return; } const args = status.hasUpstream ? ['push'] : ['push', '-u', 'origin', status.branch]; const result = await git(dir, args, { token: config.token }); if (result.ok) { pushed += 1; console.log(`${SYM.push} ${repo} ${pc.dim(`pushed ${status.branch}${status.ahead ? ` (+${status.ahead})` : ''}`)}`); } else { failures += 1; console.error(`${SYM.fail} ${repo}: ${result.stderr.trim().split('\n').pop()}`); } }); if (failures > 0) process.exit(EXIT.PARTIAL); if (pushed === 0 && targets.length > 0) console.log(pc.dim('Everything up to date.')); }); }