Files
sausage/userland/git

Git for WASI 0.2

This crate adapts the v2 Git plugin's local operations and HTTP transport. It uses gix 0.90 and the patches in vendor/PATCHES.md. It does not use the plugin SDK, RPC dispatch, the vault, or SSH. The host supplies credentials through standard wasi:http.

Build

Run the build from userland/ to include the workspace's cwd constructor:

CARGO_TARGET_DIR=/tmp/p1-git/target nix develop .. -c cargo build -p git --release

The following commands run from the repository root.

Native/WASI comparison and import check

nix develop -c nu userland/git/test.nu /tmp/p1-git/target/wasm32-wasip2/release/git.wasm

The script checks that the component imports only WASI interfaces. It creates separate native and WASI repositories under /tmp/p1-git/. It fixes both identities and timestamps. It compares stdout and exit codes without filtering command output. The initialization check normalizes only its repository path. Worktree listings compare exit codes only because their paths differ. Mutation checks also compare repository state through native Git on both fixtures. They compare status, commit IDs, parents, authors, diffs, and references. The script retains its fixtures for inspection.

wasmtime run needs -S http, including for local operations. It also needs -S cli-exit-with-code=y to preserve Git's numeric exit codes. The component uses WASI's exit-with-code, not a custom host import. The world host must enable that optional WASI function. The tests pass explicit -C paths.

Agent command forms

The comparison suite covers per-command -c key=value overrides and quiet local commands. It checks multiple revisions, detached status, branch deletion messages, and merge commit output. It also checks these forms:

  • status -sb and status --porcelain=v1.
  • log -n, --oneline, -p, --stat, and one literal path after --.
  • log --format and --pretty=format: with %H %h %s %an %ae %ad %d.
  • show --stat, show HEAD:path, and merge commits without a combined diff.
  • diff HEAD~1, diff A..B, --name-only, --name-status, and one literal path after --.
  • branch -a, -d, -D, -m, and --show-current.
  • checkout -b, switch -c, and merge --no-ff.
  • rev-parse --short HEAD, ls-files, and config --get.
  • Quiet init, commit, branch deletion, checkout, switch, merge, and rebase.
  • init in an existing repository without replacement of HEAD or configuration.
  • reset --soft, reset --hard, mixed reset HEAD~1, and reset HEAD <file>.
  • commit --amend -m, commit --amend --no-edit, and commit -F.
  • checkout <file>, checkout -- <file>, restore <file>, and restore --staged.
  • Bare stash, stash push, -m, list, pop, apply, and drop.
  • Quiet stash push, pop, and drop.
  • Lightweight tags, tag -a -m, bare tag, --list, and -d.
  • remote -v, add, remove, set-url, and get-url.
  • Clean cherry-pick and conflict resolution through --continue or --abort.

The log applies its path filter before its count limit. Stashes use ordinary Git commits and the refs/stash reflog. Stash accepts only the listed subcommands. Cherry-pick conflicts use CHERRY_PICK_HEAD and MERGE_MSG.

Unsupported forms

These forms return a usage error with exit code 129 and empty stdout. The suite checks the usage error instead of native Git's successful operation.

  • log --graph --oneline --all.
  • show of a merge that changes the same path relative to every parent, which requires a combined diff.

The CLI supports textual diffs and literal paths, not Git's complete pathspec language. The format options support the placeholders above, not Git's complete pretty-format language. The suite compares stdout and exit codes. It does not compare stderr text.

Local smart-HTTP test

Build the native fixture server:

CARGO_TARGET_DIR=/tmp/p1-git/server-target nix develop -c cargo build --manifest-path userland/git/tests/http-server/Cargo.toml

The server wraps native git http-backend without TLS. It accepts a repository directory and a readiness file. The readiness file receives the bound localhost port. Start the server in a separate terminal:

mkdir -p /tmp/p1-git/http-repos
/tmp/p1-git/server-target/debug/git-test-http-server /tmp/p1-git/http-repos /tmp/p1-git/http-port

Use that port in the integration test:

nix develop -c nu userland/git/http-test.nu /tmp/p1-git/target/wasm32-wasip2/release/git.wasm /tmp/p1-git/http-repos http://127.0.0.1:PORT/repo.git

Use a fresh repository name for each test run. The script checks anonymous clone, fetch, and push through WASI. It checks the resulting object IDs with native Git.

Anonymous HTTPS test

The host handles TLS, not the guest. Test HTTPS separately against the small public Hello-World repository:

nix develop -c nu userland/git/public-https-test.nu /tmp/p1-git/target/wasm32-wasip2/release/git.wasm

This test clones the repository and fetches it again. It does not need credentials. HTTPS push requires the host's later credential injection.