Files
IronStorage/docs/git-synchronization.md

64 lines
3.6 KiB
Markdown

# Embedded Git and synchronization
All Git behavior is implemented in `crates/storage`. IronStorage never launches
`git`, a credential helper, an SSH client, a hook, a filter, or a merge driver.
Repositories are opened with isolated configuration and environment access;
repository-local configuration that can affect an operation is rejected.
Upstream `pass git init` deliberately writes `diff.gpg.binary` and a
`diff.gpg.textconv` GnuPG command. IronStorage preserves these passive keys for
compatibility but never evaluates them: it reads Git blobs and renders decrypted
diffs through Rust storage APIs. Frontends cannot add or change diff drivers.
This behavior follows the
[upstream password-store initialization](https://git.zx2c4.com/password-store/tree/src/password-store.sh)
while keeping runtime helper execution disabled.
`GitRepository` initializes and opens password-store worktrees, selects the
innermost repository for a nested entry, and implements status, log, diff, add,
commit, remote, and local-config operations. Successful insert, edit, generate,
recipient-policy, remove, move, and copy transactions use the same concrete
committer. Only their affected paths are staged, unrelated index state is
preserved, no-op mutations create no commit, and commit failures restore the
index so the storage transaction can roll back its files.
## Remote endpoint contract
Storage parses credential-free HTTPS URLs plus feature-gated `ssh://` and
scp-like SSH URLs into one typed endpoint contract. Local paths, `git://`,
`file://`, helper transports, URL rewrites, separate push URLs, embedded
credentials, and unknown schemes are rejected before transport. A build
without the `ssh` feature reports SSH as unsupported before connection or
repository mutation instead of treating its configuration as malformed.
## HTTPS transport
HTTPS credentials are requested with the configured server ID and application
ID and remain outside Git configuration. The SSH session, host-verification,
authentication, and pack-protocol implementations are separate milestone work;
until those layers are present, network operations on SSH endpoints return the
typed unsupported-transport result.
Fetch uses the embedded Rust smart-HTTP client with an explicit credential
callback, so Git's credential cascade is never entered. Push implements the
receive-pack protocol directly: it validates the advertisement, checks the
remote tip is an ancestor, creates a complete Git pack with a SHA-1 trailer,
requests `report-status`, and accepts the update only after both unpack and ref
status succeed. HTTP redirects are disabled so authorization cannot cross an
origin boundary.
Pull refuses a dirty worktree. It fast-forwards when possible and otherwise
uses the embedded three-way tree merge. Unresolved paths are returned as typed
`MergeConflicts`; no conflict markers or partial checkout are written. Checkout
prevalidates tree entries, rejects links and submodules, writes private files
atomically, updates the real Git index, and rolls the worktree/index back if the
reference update fails. `sync` performs pull before push, while clone builds in
a private sibling directory and installs the completed vault with a rename.
Commit signing is optional. The embedded OpenPGP key store signs the canonical
unsigned commit bytes and adds an ASCII-armored `gpgsig` header compatible with
Git/GPG without invoking `gpg`.
The smart-HTTP boundary is injectable for deterministic compatibility tests.
Tests can inspect credentials, advertisements, receive-pack commands, object
counts, pack checksums, non-fast-forward behavior, and server status without a
runtime helper or external Git installation.