OverviewFilesCommitsIssuesDocsReleasesPeers

pgh / lib / commands / remote.js

77 lines · javascript ref:
/**
 * pgh remote — manage pear-style git remotes.
 *
 *   pgh remote list                          List all remotes (pear marked)
 *   pgh remote add <name> <pear-url>         Add a new remote
 *   pgh remote rm <name>                     Remove a remote
 *   pgh remote rename <old> <new>            Rename a remote
 *   pgh remote set-url <name> <url>          Update a remote's URL
 *
 * Pure local — does not connect to the v3 daemon. All operations
 * delegate to `git remote …` so the user sees standard git output.
 */

import { execFileSync } from '../_compat-exec.js'
import { listPearRemotes, runGit } from './_git-helpers.js'

export const usage = `pgh remote — manage pear-style git remotes

  pgh remote list                          List remotes (pear ones marked)
  pgh remote add <name> <pear-url>
  pgh remote rm <name>
  pgh remote rename <old> <new>
  pgh remote set-url <name> <url>

Pure local — delegates to 'git remote …'.`

export async function run (client, args) {
  const sub = args[0] || 'list'
  const rest = args.slice(1)

  switch (sub) {
    case 'list':
    case 'ls':
      return listAll()
    case 'add':
      if (rest.length < 2) throw new Error('usage: pgh remote add <name> <pear-url>')
      await runGit(['remote', 'add', rest[0], rest[1]])
      return { added: rest[0], url: rest[1] }
    case 'rm':
    case 'remove':
      if (rest.length < 1) throw new Error('usage: pgh remote rm <name>')
      await runGit(['remote', 'remove', rest[0]])
      return { removed: rest[0] }
    case 'rename':
      if (rest.length < 2) throw new Error('usage: pgh remote rename <old> <new>')
      await runGit(['remote', 'rename', rest[0], rest[1]])
      return { renamed: { from: rest[0], to: rest[1] } }
    case 'set-url':
      if (rest.length < 2) throw new Error('usage: pgh remote set-url <name> <url>')
      await runGit(['remote', 'set-url', rest[0], rest[1]])
      return { name: rest[0], url: rest[1] }
    default:
      throw new Error('unknown remote subcommand: ' + sub + '\n' + usage)
  }
}

function listAll () {
  let out
  try {
    out = execFileSync('git', ['config', '--get-regexp', 'remote\\..*\\.url'], {
      encoding: 'utf8',
      stdio: ['ignore', 'pipe', 'pipe']
    })
  } catch (err) {
    if (err.status === 1) return { remotes: [] }
    throw new Error('not in a git repo (or git config failed): ' + err.message)
  }
  const pearSet = new Set(listPearRemotes().map(r => r.name))
  const remotes = []
  for (const line of out.split('\n')) {
    const m = line.match(/^remote\.([^.]+)\.url\s+(.+)$/)
    if (!m) continue
    remotes.push({ name: m[1], url: m[2], pear: pearSet.has(m[1]) })
  }
  return { remotes }
}