Documentation
¶
Overview ¶
Package git shells out to the system git executable for ref state, reachability, patch identity, and backflow branch construction. Oiax does not implement Git object semantics itself — Git is already exceptionally good at being Git.
Security invariant: branch and ref names are passed to git as data (after `--` separators where the subcommand accepts one, and validated with `git check-ref-format`), never interpolated into a shell.
Index ¶
- type CherryPickConflict
- type Commit
- type Runner
- func (r *Runner) BranchExists(ctx context.Context, name string) (bool, error)
- func (r *Runner) CheckRefFormat(ctx context.Context, name string) error
- func (r *Runner) CherryPick(ctx context.Context, shas []string) (string, error)
- func (r *Runner) CommitExists(ctx context.Context, oid string) (bool, error)
- func (r *Runner) DefaultBranchRef(ctx context.Context) (string, bool)
- func (r *Runner) Head(ctx context.Context, name string) (string, error)
- func (r *Runner) IsAncestor(ctx context.Context, ancestor, descendant string) (bool, error)
- func (r *Runner) IsShallowRepository(ctx context.Context) (bool, error)
- func (r *Runner) MergeBase(ctx context.Context, a, b string) (string, error)
- func (r *Runner) PatchIDs(ctx context.Context, base, tip string) (map[string]string, error)
- func (r *Runner) RemoteTrackingHead(ctx context.Context, name string) (string, bool, error)
- func (r *Runner) RequireMinVersion(ctx context.Context) error
- func (r *Runner) ResolveCommit(ctx context.Context, oid string) (string, error)
- func (r *Runner) ShortSHA(ctx context.Context, branch string) (string, error)
- func (r *Runner) ShowFile(ctx context.Context, ref, path string) ([]byte, error)
- func (r *Runner) TreeSHA(ctx context.Context, branch string) (string, error)
- func (r *Runner) UniqueCommits(ctx context.Context, base, branch string) ([]Commit, error)
- func (r *Runner) Version(ctx context.Context) (string, error)
- func (r *Runner) Worktree(ctx context.Context, ref string) (*Runner, func(), error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CherryPickConflict ¶
type CherryPickConflict struct {
// SHA is the object id of the commit that failed to apply.
SHA string
// Subject is the failing commit's subject line (git show -s --format=%s).
Subject string
// Applied is the number of commits that cherry-picked cleanly before the
// failure (0 means the very first commit conflicted).
Applied int
}
CherryPickConflict reports that a cherry-pick sequence stopped on a commit whose content genuinely conflicted with the target (git exit code 1). It carries enough to surface a reported divergence without any git state: the failing commit, its subject, and how many earlier commits applied cleanly before it. The worktree has been reset with `git cherry-pick --abort` by the time this error is returned. Operational failures (a killed subprocess, a cancelled context, a structural refusal such as a merge commit) are NOT CherryPickConflicts — they propagate as ordinary errors so a transient problem is not misreported as a human-actionable content conflict.
func (*CherryPickConflict) Error ¶
func (e *CherryPickConflict) Error() string
type Commit ¶
Commit is one observed commit. It is git-local; the coordination layer maps it to the engine's own commit type.
type Runner ¶
type Runner struct {
// Dir is the repository working directory. Empty means the current
// directory.
Dir string
// Env, when non-empty, is appended to the inherited process environment
// for every git invocation. It exists so a cherry-pick can pin the
// committer identity and date (making the replayed SHA a deterministic
// function of its inputs); it is not safe for concurrent use, so set it
// only on a Runner bound to an ephemeral worktree.
Env []string
}
Runner executes git commands in one repository working directory.
func (*Runner) BranchExists ¶
BranchExists reports whether a local branch ref exists. It is deliberately local-only (unlike resolveBranchRef, which also considers origin-tracking refs); it has no callers today and its strictly-local semantics are kept for the case a caller needs exactly "is this a materialized local head".
func (*Runner) CheckRefFormat ¶
CheckRefFormat rejects names that are not well-formed branch names. Every configured branch name passes through here before being used in any other git invocation.
func (*Runner) CherryPick ¶
CherryPick replays shas onto the Runner's checked-out HEAD one at a time with `git cherry-pick -x` (each replayed commit records a "(cherry picked from commit <sha>)" provenance trailer). shas must be in application order, oldest first. It is intended to run against a Runner bound to an ephemeral Worktree, never the caller's checkout.
Each pick pins the committer identity and date to the ORIGINAL commit's, so the replayed HEAD is a deterministic function of its inputs: cherry-pick otherwise stamps the committer date to "now", giving a different HEAD SHA on every run and making the force-push that follows never a no-op (it would churn the managed branch and the open request's head on every reconcile).
`--empty=drop` skips a pick that reduces to an empty diff because its change is already present on the target (a redundant return): that is convergence, not a conflict.
On full success it returns the new HEAD object id. On the first commit whose content genuinely conflicts (git exit code 1) it runs `git cherry-pick --abort` (leaving the worktree clean) and returns a *CherryPickConflict naming that commit and the count of commits applied cleanly before it; nothing is pushed. Any other failure (exit code other than 1: a cancelled context, a killed subprocess, a structural refusal) propagates as an ordinary error rather than a *CherryPickConflict. Each sha is guarded with oidPattern before use.
func (*Runner) CommitExists ¶
CommitExists reports whether oid resolves to a commit object present in the local repository. It exists to distinguish a DEFINITIVE not-found — git's `rev-parse --verify --quiet` exit 1, meaning the object is simply not in the object database — from an operational failure (any other error), which propagates. A caller can then act on a genuinely absent commit (e.g. a backflow request whose encoded source head was history-rewritten out of existence) without mistaking a transient git failure for absence. oid is guarded with oidPattern, exactly as ResolveCommit guards it.
func (*Runner) DefaultBranchRef ¶
DefaultBranchRef resolves the repository's default branch to its remote-tracking ref (for example "origin/main"). It first reads origin/HEAD, the symbolic ref git records locally for the remote's default branch. When that is unset — a checkout that never ran `git remote set-head`, as under actions/checkout — it falls back to asking the remote directly with `git ls-remote --symref origin HEAD`, whose "ref: refs/heads/<name>\tHEAD" line names the default branch without depending on any local ref. The second return is false when both the local symref and the remote query fail (a remote-less repository), leaving the choice of fallback to the caller. It is also false when the remote query names a branch whose local tracking ref was never fetched: the resolved ref is only useful if `git show origin/<name>:<path>` can read it, and ls-remote confirms the remote's default without materializing refs/remotes/origin/<name> — so a single-branch checkout of a non-default branch would otherwise report a ref the sole consumer (config read) cannot open. A remote-tracking ref (not the local branch of the same name) is returned deliberately: it is the authoritative committed state of the default branch, independent of any stale local branch.
func (*Runner) Head ¶
Head resolves a branch name to its commit SHA. The name is resolved to its local head or origin-tracking ref (resolveBranchRef), so a branch that actions/checkout left only as refs/remotes/origin/<name> still resolves.
func (*Runner) IsAncestor ¶
IsAncestor reports whether ancestor is reachable from descendant (git merge-base --is-ancestor). Both arguments are object ids from prior git output and are guarded as such. Exit 0 ⇒ true, exit 1 ⇒ false, any other failure is an error.
func (*Runner) IsShallowRepository ¶
IsShallowRepository reports whether the working repository is a shallow clone — the state actions/checkout produces by default (fetch-depth: 1), where only a truncated slice of history is present. A shallow clone has no merge base for branches whose fork point predates the fetch depth, so the patch-identity and baseline rungs of the equivalence ladder silently switch off and already-promoted content looks unpromoted. The coordinator surfaces a warning on this signal rather than emit spurious promotion requests. It reads `git rev-parse --is-shallow-repository`, which prints "true"/"false".
func (*Runner) MergeBase ¶
MergeBase returns the best common ancestor of two branches. It returns ("", nil) when the branches share no common ancestor (git exit code 1), mirroring BranchExists; any other failure is an error.
func (*Runner) PatchIDs ¶
PatchIDs returns the stable patch-id of every non-merge commit in the range base..tip, keyed by commit SHA. Merge commits contribute no entry. tip must be a branch name; base may be a branch name or an object id (e.g. a merge base). The patch-id is content-based, so it survives a rebase that rewrites commit SHAs without changing the diff.
func (*Runner) RemoteTrackingHead ¶
RemoteTrackingHead resolves a branch's origin-tracking ref (refs/remotes/origin/<name>) to its commit SHA, reporting ok=false when the tracking ref does not exist. Unlike resolveBranchRef it never falls back to a local head: it reports specifically the branch's last-fetched remote state. It backs the backflow push guard — before force-pushing the deterministic backflow branch, the coordinator compares the freshly replayed head against the branch's already-pushed head and skips an unchanged re-push, so a steady replay does not churn the open request. The name is validated with CheckRefFormat and only refs/remotes/origin/<validated> is constructed, preserving the no-shell and ref-format guarantees. A resolution failure that is git's clean "no such ref" (exit 1) is reported as ok=false; any other failure propagates.
func (*Runner) RequireMinVersion ¶
RequireMinVersion asserts the system git is at least the version oiax needs (see minGitMajor/minGitMinor) and returns a clear error naming both the required floor and the detected version otherwise. It is meant to run once at startup, before any git-dependent work, so an unsupported runner fails fast rather than deep inside a backflow cherry-pick.
func (*Runner) ResolveCommit ¶
ResolveCommit resolves an object id (or an unambiguous abbreviation of one) to its full commit SHA. The input is guarded with oidPattern so it can only be a hex object id, never an option or a ref expression; it is used to turn the short SHA encoded in a backflow branch name back into a commit for an ancestry test. A resolution failure (unknown/ambiguous object) is returned as an error so callers can treat an unresolvable prior head conservatively.
func (*Runner) ShortSHA ¶
ShortSHA resolves a branch head to a fixed-length abbreviated object id (git rev-parse --short=12). Backflow branch names embed the short SHA of the downstream source head so a given head deterministically yields one branch name (the concurrency strategy); the abbreviation length is fixed so that name depends only on the head, not on local object-database state. The branch name is validated through CheckRefFormat and passed as a fully-qualified ref.
func (*Runner) ShowFile ¶
ShowFile returns the contents of path as committed at ref (`git show <ref>:<path>`). This is how the pinned-configuration-ref rule is implemented: configuration is read from one ref per invocation, never from the working tree of whatever triggered the run.
func (*Runner) TreeSHA ¶
TreeSHA returns the tree object SHA of a branch head. Equal trees on two branches mean identical content even when the commits differ (the head-tree rung, which detects a squash at the moment of merge).
func (*Runner) UniqueCommits ¶
UniqueCommits returns commits reachable from branch but not from base (git range base..branch), newest first, with subjects. A nil slice means the range is empty — the reachability rung's "in sync" signal.
func (*Runner) Version ¶
Version reports the raw `git version` line ("git version 2.45.1"). RequireMinVersion parses it to assert the required floor; it is also useful for diagnostics.
func (*Runner) Worktree ¶
Worktree creates an ephemeral, detached working tree checked out at ref (git worktree add --detach). It exists so mutating operations — chiefly a cherry-pick sequence — never touch the caller's checked-out branch or index. It returns a Runner bound to the new tree and a cleanup func that removes the worktree registration and its directory; the caller MUST invoke cleanup on every exit path (defer it). ref accepts either a branch name (validated and fully qualified) or a bare object id, mirroring validRev, so the target head may be supplied as either.