OverviewFilesCommitsIssuesDocsReleasesPeers

pgh / lib / commands / clone.js

62 lines · javascript ref:
/** pgh clone <repo> [dest] — clone over gip (local materialized repo) with
 *  a legacy-URL fallback.
 *
 *  gip-overlay path: the daemon materializes each repo's bare repo locally —
 *  refs via the per-repo autobase, objects via the overlay bundle chain — so
 *  the bytes are already on this host. We clone from that local bare repo
 *  instead of fetching over git-upload-pack across the swarm. (pgh runs on the
 *  daemon's host.) This is the read path that retires hyper-sync's upload-pack
 *  for full peers; receive-pack (push) is unchanged, and lightweight cloners
 *  with no local daemon still use the legacy URL fallback below.
 */

import fs from '#node:fs'

import { execFileSync } from '../_compat-exec.js'

const ALLOWED_SCHEMES = ['punch://', 'pear://', 'git+pear://', 'https://', 'http://', 'ssh://', 'git://', 'git@']

export const usage = `pgh clone — clone a daemon-served repo over gip

  pgh clone <repo> [dest]

Clones from the daemon's locally-materialized bare repo (refs via the
per-repo autobase, objects via the overlay) when available, falling back
to the legacy clone URL otherwise.`

export async function run (client, args, opts = {}) {
  const exec = opts.exec || execFileSync
  const exists = opts.exists || fs.existsSync

  const repo = args[0]
  if (!repo) throw new Error('usage: pgh clone <repo> [dest]')
  const dest = args[1]

  const got = await client.call('get-repo', { name: repo })
  if (!got) throw new Error('repo not found: ' + repo)
  const info = got.info || {}

  // ── gip path: clone from the locally-materialized bare repo ──────
  if (info.path && exists(info.path)) {
    console.log('Cloning ' + repo + ' from local gip repo ' + info.path)
    exec('git', ['clone', '--', info.path, ...(dest ? [dest] : [])], { stdio: 'inherit' })
    return null
  }

  // ── fallback: legacy URL clone (hyper-sync upload-pack / HTTP) ───
  const url = got.punchUrl || info.httpUrl || info.cloneUrl
  if (!url) {
    throw new Error('repo not materialized locally — run `pgh repo join <invitation>` first (no clone URL available)')
  }
  // Validate scheme — the URL came over RPC (trusted on UDS, NOT over swarm).
  // execFileSync's array form blocks shell injection, but a URL like
  // `--upload-pack=…` would be parsed by git as a flag. The leading `--`
  // below separates flags from positionals; the scheme check is defence in depth.
  if (!ALLOWED_SCHEMES.some(s => url.startsWith(s))) {
    throw new Error('refusing to clone from URL with unrecognised scheme: ' + url)
  }
  console.log('Cloning ' + repo + ' from ' + url)
  exec('git', ['clone', '--', url, ...(dest ? [dest] : [])], { stdio: 'inherit' })
  return null
}