cmux-tui: git-seed-v1, seed a Cloud project from its GitHub remote plus a diff bundle

Merged
TE
4d ago
+2984-13

Leo, on the start screen's "Your project folder is copied up." line:

Your project folder is copied up. / we'll want to deal with the edge cases for this too

This is piece 3 of the Cloud project seed (design: leo-workspace design/cloud.md, "Getting the project onto the machine"). It is the machine side only: the daemon op git-seed-v1 in cmux-tui-core (src/git_seed.rs, src/git_seed/). The machine clones the project's GitHub remote at a base commit, then applies one small git bundle the Mac uploads through fs-v1. That bundle holds only the local diff: HEAD's unpushed commits plus INDEX, WORK and stash commits. The Mac side and the cmux link start-chat copy wiring are separate PRs.

Wire

Served only where fs-v1 is (Cloud hosts), under the same roots. A frame is admitted by the link entry's remote gate (FsGate) next to the seven fs ops, and by nothing else. Answers use the fs-v1 envelope: {id, ok:true, data} or {id, ok:false, error, error_code}.

  • git.seed.start returns {job} at once, and the work runs on its own thread. A retry with the same folder, bundle and WORK (or the same folder and ref for a clone) returns the running or finished job.
    • Seed: {folder, url, repo, base, bundle, head_ref|null, head, index, work, stash|null, sparse|null, lfs}.
    • Delta seed: the same plus since (the folder's last WORK). It uses no network unless a submodule changed.
    • Clone only: {folder, url, repo, ref?, lfs?}, with no bundle and no shas.
  • git.seed.status {job} returns {job, state: running|done|failed, phase: clone|fetch|bundle|checkout|submodules|lfs, progress: {received_bytes, objects, total_objects}, notes: [lfs_unavailable|lfs_failed], head?, head_ref?, error_code?, error?, install_url?}.
  • Error codes:
    • Answered at once: seed.bad_request, seed.unknown_job, seed.unavailable (not a Cloud host), seed.permission_denied (wrong transport).
    • Reported in a failed job's status: seed.folder_not_empty, seed.base_missing, seed.bundle_invalid, seed.checkout_failed, seed.clone_failed, seed.needs_github (+ install_url when cmux github credential names one), seed.disk_full, seed.since_mismatch, seed.machine_changed.

Edge cases handled

  • Validation. url must be exactly https://github.com/OWNER/NAME.git and match repo. Shas must be full lowercase hex. head_ref must be under refs/heads/ and pass git check-ref-format. ref uses CloudMachineRepo's safe subset.
  • Sandbox. The folder and bundle must lie strictly under an fs-v1 root. No ./.. components are allowed, the deepest existing ancestor is canonicalized, and a symlink out of the root is refused.
  • Credentials. The order and environment match CloudMachineRepo's repo step: lane helper, then cmux github credential, then anonymous. Prompts, askpass and traces are off, GIT_CONFIG_GLOBAL=/dev/null and GIT_CONFIG_NOSYSTEM=1 are set, and credential.helper= is reset before the chosen helper with useHttpPath. No token comes from the Mac.
  • No hooks, https only. Every git call runs with core.hooksPath=/dev/null, core.fsmonitor=false, protocol.allow=never and protocol.https.allow=always. The bundle fetch alone allows the file transport, and runs with transfer.fsckObjects=true.
  • Checkout. The branch is placed at HEAD and tracks origin/<branch> when that exists; otherwise HEAD is detached. The working tree is set to WORK with read-tree -u, then the index to INDEX, and refs/stash is set. Non-cone sparse patterns are kept, and untracked files outside them are written from the bundle's blobs.
  • Re-seeding a folder. A re-seed of the same folder fetches instead of cloning, and git clean drops the previous seed's untracked files while ignored ones stay.
  • Delta seeds. A delta seed refuses a machine whose HEAD, index or working tree changed since the last seed, and changes nothing in that case.
  • Cleanup. A clone that fails partway is removed. The bundle is deleted once it has been applied.

Tests (cargo, no network)

A file:// bare remote stands in for GitHub through a test-only url.<file>.insteadOf config. A "Mac" checkout builds the bundle the way the Mac side does. The tests cover:

  • a full seed (branch, head, index, worktree, untracked files, stash and status all equal);
  • a detached HEAD, upstream tracking, and sparse checkout;
  • base_missing, a non-empty folder, paths outside the roots, and bad url, sha and ref;
  • idempotent retry, and hooks not running;
  • a delta seed (edit, add, delete, with the remote deleted), since_mismatch and machine_changed;
  • clone-only at the default branch and at a tag;
  • the gate tests in fs_wire_tests.rs and link/tests.rs.

Agent session: agent session

šŸ¤– Generated with Claude Code