/**
* pgh push - Push to pear remote
*
* Auto-detects pear://, punch://, git+pear://, or named 'pear' remote.
* Supports --recurse-submodules for @pear-marked submodules.
*/
import path from 'bare-path'
import { log, error, jsonOut } from '../output.js'
import { gitExec, gitSpawn, findPearRemote, parseGitmodules } from '../git.js'
export async function pushCommand (client, sub, args, flags) {
// sub is actually the first positional after 'push' (e.g. branch name)
// Collect refs from sub + args
const refs = []
if (sub) refs.push(sub)
refs.push(...args)
const cwd = await gitExec(['rev-parse', '--show-toplevel'], '.')
const remote = await findPearRemote(cwd)
if (!remote) {
error('No pear remote found. Run "pgh repo link <name> <path>" to add one.')
}
// Build git push args
const gitArgs = ['push']
if (flags.force) gitArgs.push('--force')
if (flags.u || flags['set-upstream']) gitArgs.push('--set-upstream')
gitArgs.push(remote)
if (refs.length > 0) {
gitArgs.push(...refs)
}
const results = { remote, refs, submodules: [] }
try {
if (flags.json) {
const output = await gitExec(gitArgs, cwd)
if (output) log(output)
} else {
await gitSpawn(gitArgs, cwd)
}
results.status = 'ok'
} catch (err) {
if (flags.json) {
results.status = 'error'
results.error = err.message
jsonOut(results)
process.exit(1)
}
throw err
}
// Handle --recurse-submodules
if (flags['recurse-submodules']) {
await pushSubmodules(cwd, refs, flags, results)
}
if (flags.json) {
jsonOut(results)
}
}
async function pushSubmodules (cwd, refs, flags, results) {
let content
try {
content = await gitExec(['show', 'HEAD:.gitmodules'], cwd)
} catch {
if (!flags.json) log('No .gitmodules found - skipping submodules')
return
}
const submodules = parseGitmodules(content)
const pearSubs = submodules.filter(s => s.pear && s.path)
if (pearSubs.length === 0) {
if (!flags.json) log('No @pear submodules found')
return
}
for (const sub of pearSubs) {
const subPath = path.resolve(cwd, sub.path)
if (!flags.json) log(`\nPushing submodule: ${sub.name}`)
const subRemote = await findPearRemote(subPath)
if (!subRemote) {
const msg = `No pear remote in submodule ${sub.name} - skipping`
if (!flags.json) log(` ${msg}`)
results.submodules.push({ name: sub.name, status: 'skipped', reason: msg })
continue
}
const subArgs = ['push']
if (flags.force) subArgs.push('--force')
subArgs.push(subRemote)
if (refs.length > 0) subArgs.push(...refs)
try {
if (flags.json) {
await gitExec(subArgs, subPath)
} else {
await gitSpawn(subArgs, subPath)
}
results.submodules.push({ name: sub.name, status: 'ok' })
} catch (err) {
if (!flags.json) console.error(` Failed: ${err.message}`)
results.submodules.push({ name: sub.name, status: 'error', error: err.message })
}
}
}
export function pushHelp () {
log(`Usage: pgh push [refs...] [flags]
Push to the pear remote (auto-detected from pear://, punch://, git+pear://, or named 'pear').
Arguments:
[refs...] Branch or refspec to push (default: current branch)
Flags:
--force Force push
-u, --set-upstream Set upstream tracking
--recurse-submodules Push @pear-marked submodules too
--json Output as JSON
Examples:
pgh push Push current branch
pgh push main Push main branch
pgh push --force main Force push main
pgh push -u feature-branch Push and set upstream
pgh push --recurse-submodules Push main repo + submodules`)
}