Documentation
¶
Overview ¶
Package git is awf's one semantic git seam: every git capability the application needs is an entrypoint here, and which backend answers an entrypoint (in-process object reads, or native Git through the package runner) is an implementation detail no consumer can observe. A handle opened with Open or OpenContaining carries the read entrypoints as methods; the pure range parser and the repository-topology entrypoints stay free functions because they precede or do without an opened repository. No backend type, sentinel, or error value crosses the seam surface in either direction.
This file holds the go-git backend: the tolerant repository open and the object, tree, and ignore reads the handle's methods are implemented with.
Index ¶
- Constants
- Variables
- func MergeHeads(projectRoot string) ([]string, error)
- func MergeInProgress(projectRoot string) (bool, error)
- func ParseRange(arg string, allowBareBase bool) (base, head string, err error)
- func ProjectResidentRoot(ctx context.Context, invocationPath string) string
- type Action
- type BlobMode
- type CommandError
- type Commit
- type CommitPolicyError
- type CommitPolicyErrorKind
- type ControlRoots
- type FileChange
- type HardSafetyError
- type IndexBlob
- type Repo
- func (r *Repo) Ancestor(ctx context.Context, older, newer string) (bool, error)
- func (r *Repo) BranchDelete(ctx context.Context, name string) error
- func (r *Repo) BranchExists(ctx context.Context, name string) (bool, error)
- func (r *Repo) Branches(ctx context.Context) (map[string]bool, error)
- func (r *Repo) ChangeCounts(ctx context.Context) (tracked, untracked int, err error)
- func (r *Repo) ChangedPaths(ctx context.Context, staged bool, rangeSpec string) ([]string, error)
- func (r *Repo) CommitBlobs(ctx context.Context, rev string) ([]IndexBlob, error)
- func (r *Repo) CommitBlobsAt(ctx context.Context, rev string, paths []string) ([]IndexBlob, error)
- func (r *Repo) CommitEntries(ctx context.Context, rev string) ([]TreeEntry, error)
- func (r *Repo) CommitFacts(ctx context.Context, id string) (commitpolicy.Commit, error)
- func (r *Repo) CommitMessage(ctx context.Context, rev string) (string, error)
- func (r *Repo) CommitParents(ctx context.Context, rev string) ([]string, error)
- func (r *Repo) CommitsAfter(ctx context.Context, baseline string, targets []string) ([]commitpolicy.Commit, error)
- func (r *Repo) CurrentBranch(ctx context.Context) (string, error)
- func (r *Repo) FileText(ctx context.Context, rev, path string) (text string, found bool, err error)
- func (r *Repo) FirstParentChangedPaths(ctx context.Context, rev string) ([]string, error)
- func (r *Repo) FullOID(ctx context.Context, rev string) (string, string, error)
- func (r *Repo) GitPath(ctx context.Context, name string) (string, error)
- func (r *Repo) HeadExists(ctx context.Context) (bool, error)
- func (r *Repo) HeadHash(ctx context.Context) (string, error)
- func (r *Repo) IndexBlobs(ctx context.Context) ([]IndexBlob, error)
- func (r *Repo) MergeBase(ctx context.Context, a, b string) (string, error)
- func (r *Repo) MergeFastForward(ctx context.Context, rev string) error
- func (r *Repo) MergeNoCommit(ctx context.Context, rev string) error
- func (r *Repo) PeelCommit(ctx context.Context, rev string) (string, string, error)
- func (r *Repo) RangeBlobs(ctx context.Context, rev string) (before, after []IndexBlob, err error)
- func (r *Repo) RangeChangedPaths(ctx context.Context, base, head string) ([]string, error)
- func (r *Repo) RangeDiffText(ctx context.Context, base, head string) (string, error)
- func (r *Repo) ResolveCommit(ctx context.Context, revision string) (string, error)
- func (r *Repo) Root() string
- func (r *Repo) ValidateRefName(ctx context.Context, name string) (bool, error)
- func (r *Repo) VerifySSH(ctx context.Context, id string, signers []commitpolicy.Signer) (verdict commitpolicy.SignatureVerdict, retErr error)
- func (r *Repo) WalkRangeCommits(ctx context.Context, base, head string, visit func(Commit) error) (int, error)
- func (r *Repo) WorkingPaths(ctx context.Context) ([]string, error)
- func (r *Repo) WorktreeAdd(ctx context.Context, path, branch, base string) error
- func (r *Repo) WorktreeList(ctx context.Context) ([]WorktreeRegistration, error)
- func (r *Repo) WorktreePrune(ctx context.Context) error
- func (r *Repo) WorktreeRemove(ctx context.Context, path string) error
- type ResidentName
- type TreeEntry
- type WorktreeRegistration
Constants ¶
const CommandTimeout = 2 * time.Minute
CommandTimeout is the hang-prevention ceiling a command boundary puts on the git work it starts. The seam owns the VALUE while each boundary still chooses to apply it, which is what keeps one number rather than one per binary: it was three copies before this const existed, and a ceiling that drifts between binaries is a ceiling nobody can reason about. It is generous enough that no observed-normal operation approaches it, so a command that reaches it has stalled rather than merely taken a while.
internal/testsupport keeps its own copy, forced by the same zero-internal-deps rule that forces the fixture lane's isolation duplicate.
Variables ¶
var ErrIndexBlob = errors.New("read index blob")
ErrIndexBlob reports a stage-0 regular-file entry whose content cannot be read from the object store.
var ErrIndexUnmerged = errors.New("index contains unmerged entries")
ErrIndexUnmerged reports an index that has multiple merge stages and cannot represent one deterministic pre-commit snapshot.
var ErrNotARepository = errors.New("not a git repository")
ErrNotARepository reports a path that carries no Git repository. It is the seam's own not-a-repository identity: a consumer matches it with errors.Is and never sees the backend sentinel it translates, so which backend answered the open stays an implementation detail.
Functions ¶
func MergeHeads ¶ added in v0.30.0
MergeHeads returns every worktree-private MERGE_HEAD hash in file order. Absence means no merge is in progress and returns a nil slice.
func MergeInProgress ¶ added in v0.30.0
MergeInProgress reports whether the checkout containing projectRoot has a merge in progress, detected by the presence of MERGE_HEAD.
MERGE_HEAD is worktree-private, so it lives in a linked worktree's own gitdir rather than the shared common dir, and a project root may sit below the checkout root. A naive <root>/.git lookup is wrong for both, so resolution walks up to the containing checkout and reuses worktreeGitDir, which already resolves a `.git` directory or a validated `gitdir:` pointer (ADR-0182 item 4).
Detection is by repository state rather than by the shape of the staged diff. It must stay true through a conflict resolution, where the merge is committed by a later `git commit`, and false for a hand-staged commit that merely looks branch-sized. `git merge --squash` records no MERGE_HEAD and so reports false, which is correct: it produces an ordinary commit carrying no merge provenance.
func ParseRange ¶ added in v0.18.0
ParseRange resolves a range argument to an explicit base and head revision. An argument containing ".." is a two-sided range; otherwise it is a base and head defaults to HEAD, which callers opt into via allowBareBase (ADR-0127 Decision 5). Git forbids ".." inside a ref name, so the discrimination is unambiguous. Rejects an empty side, a three-dot range, a multi-".." input, and a "-"-prefixed side: the first three would reach git as a bogus revision and the last as an option-like argument. Dots inside a revision (v0.10.0) are legal, since git forbids "."-leading, ".."-containing, and "-"-leading refs.
func ProjectResidentRoot ¶ added in v0.30.0
ProjectResidentRoot maps an invoking checkout to the checkout that owns the project's resident awf state. It is the one home for that resolution: the composition point in cmd/awf and the transitional project opener both call it, so the rule that resident state belongs to the primary checkout cannot drift between them.
Any failure to resolve the topology returns invocationPath unchanged, which is the only answer that keeps a non-Git tree, a fixture tree, and an unresolvable checkout usable: resident state then lives where the command was invoked. The seam already owns both steps (ResolveControlRoots and ResidentRoot), so this adds no dependency in either direction.
Types ¶
type BlobMode ¶ added in v0.22.0
type BlobMode uint8
BlobMode is the closed set of Git blob modes preserved by snapshots.
type CommandError ¶ added in v0.30.0
CommandError reports a native Git invocation that exited non-zero. It carries the exact arguments, the exit code, and the captured stderr so a caller can match the failure with errors.As and report what Git itself said, without the caller ever touching os/exec.
func (*CommandError) Error ¶ added in v0.30.0
func (e *CommandError) Error() string
func (*CommandError) Unwrap ¶ added in v0.30.0
func (e *CommandError) Unwrap() error
type Commit ¶ added in v0.30.0
type Commit struct {
Hash string
Revision string
Subject string
Body string
Message string
Parents []string
IsMerge bool
Changes []FileChange
}
Commit is the semantic view of one range commit.
type CommitPolicyError ¶ added in v0.30.0
type CommitPolicyError struct {
Kind CommitPolicyErrorKind
Target string
Err error
}
CommitPolicyError preserves one operational Git failure for project-level translation.
func (*CommitPolicyError) Error ¶ added in v0.30.0
func (e *CommitPolicyError) Error() string
func (*CommitPolicyError) Unwrap ¶ added in v0.30.0
func (e *CommitPolicyError) Unwrap() error
type CommitPolicyErrorKind ¶ added in v0.30.0
type CommitPolicyErrorKind string
CommitPolicyErrorKind identifies the Git operation that prevented policy evaluation.
const ( CommitPolicyBaselineError CommitPolicyErrorKind = "baseline" CommitPolicyRevisionError CommitPolicyErrorKind = "revision-resolution" CommitPolicyTagPeelError CommitPolicyErrorKind = "tag-peel" CommitPolicyTrustError CommitPolicyErrorKind = "temporary-trust-file" CommitPolicyVerifyError CommitPolicyErrorKind = "signature-process" )
type ControlRoots ¶ added in v0.30.0
ControlRoots identifies the invoking checkout, repository-wide Git common directory, and primary checkout that owns resident awf state.
func ResolveControlRoots ¶ added in v0.30.0
func ResolveControlRoots(ctx context.Context, root string) (ControlRoots, error)
ResolveControlRoots derives the checkout-local and repository-wide control roots using native Git. Native Git is used only for topology discovery; OpenRepo remains the package's read-only go-git boundary.
func (ControlRoots) ResidentRoot ¶ added in v0.30.0
func (r ControlRoots) ResidentRoot(name ResidentName) (string, error)
ResidentRoot returns one closed resident root after proving that every existing component beneath PrimaryRoot is non-symlinked and current-owned.
type FileChange ¶ added in v0.30.0
type FileChange struct {
Path string
OldPath string
Action Action
Added, Deleted int
OldText, NewText string
}
FileChange is one file touched by a commit. OldText/NewText are populated only for markdown files, empty otherwise.
type HardSafetyError ¶ added in v0.30.0
HardSafetyError marks a safety refusal that cannot be overridden by force.
func (*HardSafetyError) Error ¶ added in v0.30.0
func (e *HardSafetyError) Error() string
func (*HardSafetyError) Forceable ¶ added in v0.30.0
func (*HardSafetyError) Forceable() bool
Forceable reports whether the refusal may be overridden.
func (*HardSafetyError) Unwrap ¶ added in v0.30.0
func (e *HardSafetyError) Unwrap() error
type IndexBlob ¶ added in v0.18.0
IndexBlob is one file's exact bytes and mode from a stage-0 index or a resolved commit tree. Symlink bytes are the inert link target.
type Repo ¶ added in v0.30.0
type Repo struct {
// contains filtered or unexported fields
}
Repo is the seam's handle on one opened repository. It is constructed once, at a composition point that owns a validated root, and every read entrypoint hangs off it as a method taking the operation's context: no entrypoint re-opens the repository, and no backend type crosses the handle's surface.
prefix is the repository-relative slash-separated path of root, empty when root is the repository root itself. It is what lets an adopted project nested inside a containing monorepo read only its own paths.
func Open ¶ added in v0.30.0
Open opens the repository at root exactly, tolerating the layouts awf must read (a linked worktree's `gitdir:` pointer, a submodule, a stray `extensions.worktreeConfig`), and validates root once so every later operation reuses that validation. A path carrying no repository at all is reported as ErrNotARepository; a present but malformed checkout keeps its own error, because the two must never be confused by a caller deciding whether a checkout exists.
func OpenContaining ¶ added in v0.30.0
OpenContaining opens the repository containing start and reports start's repository-relative slash-separated prefix, empty when start is itself the repository root. The returned handle stays anchored at start, so its reads are scoped to that subtree exactly as a command invoked there expects.
func (*Repo) Ancestor ¶ added in v0.30.0
Ancestor reports whether older is an ancestor of newer. Unrelated histories answer false rather than failing, which is what makes this usable as the merged-ness test before a destructive operation.
func (*Repo) BranchDelete ¶ added in v0.30.0
BranchDelete deletes the local branch name, refusing when it is unmerged. The safe form is the only one offered: a caller that wants to discard unmerged work must do it explicitly with native Git rather than through awf.
func (*Repo) BranchExists ¶ added in v0.30.0
BranchExists reports whether the local branch name exists. Absence is an answer, not a failure.
func (*Repo) Branches ¶ added in v0.30.0
Branches returns the repository's local branch short names.
func (*Repo) ChangeCounts ¶ added in v0.30.0
ChangeCounts returns native Git's tracked-change and nonignored untracked-file counts for the handle's worktree. Native porcelain is the cleanliness oracle because go-git's status traversal can re-include a nested .gitignore below an ignored parent directory. It runs through the package runner, so it inherits the isolated environment and reports a failure with Git's own stderr; the isolation's stripped user and system config is restored for ignore purposes alone by replaying the effective core.excludesFile (see excludesFileArgs), so the oracle keeps real Git's ignore universe.
func (*Repo) ChangedPaths ¶ added in v0.30.0
ChangedPaths returns the sorted, unique repo-relative paths changed either in the staged index (staged) or between the two revisions of rangeSpec ("a..b"). staged takes precedence; with neither selector the caller should not call this. A malformed range or an unresolvable revision is a clear error. It reads the repository only.
func (*Repo) CommitBlobs ¶ added in v0.30.0
CommitBlobs returns the sorted regular and executable blobs of the tree that rev resolves to. Symlinks and gitlinks carry no regular-file content to scan and are skipped. It reads the repository only.
func (*Repo) CommitBlobsAt ¶ added in v0.30.0
CommitBlobsAt returns the sorted exact blobs selected by canonical, project-relative paths in rev. Every requested path must name a regular, executable, or symlink entry in the handle's project subtree.
func (*Repo) CommitEntries ¶ added in v0.30.0
CommitEntries returns the sorted metadata for every regular, executable, or symlink entry in rev's tree scoped to the handle's project root. It does not read blob objects; gitlinks and unsupported entries are omitted.
func (*Repo) CommitFacts ¶ added in v0.30.0
CommitFacts loads immutable author and committer facts for one commit object.
func (*Repo) CommitMessage ¶ added in v0.30.0
CommitMessage returns the full message recorded by rev.
func (*Repo) CommitParents ¶ added in v0.30.0
CommitParents returns the full parent hashes of rev in recorded order.
func (*Repo) CommitsAfter ¶ added in v0.30.0
func (r *Repo) CommitsAfter(ctx context.Context, baseline string, targets []string) ([]commitpolicy.Commit, error)
CommitsAfter expands explicit revision or range targets to unique commits after baseline.
func (*Repo) CurrentBranch ¶ added in v0.30.0
CurrentBranch returns the short name of the branch HEAD points at, or the empty string when HEAD is detached. A detached HEAD is a state of the repository, not a fault, so it is reported rather than raised.
func (*Repo) FileText ¶ added in v0.30.0
FileText reads path from rev. path is relative to the handle root. A missing path returns found false; revision and object failures remain errors.
func (*Repo) FirstParentChangedPaths ¶ added in v0.30.0
FirstParentChangedPaths returns sorted, unique paths changed by rev relative to its first parent. Roots compare against the empty tree and merges compare only against their first parent. Paths are rerooted to the handle root.
func (*Repo) FullOID ¶ added in v0.30.0
FullOID resolves rev to its complete object ID and Git object type.
func (*Repo) GitPath ¶ added in v0.30.0
GitPath resolves a repository control file name (MERGE_HEAD, rebase-merge, and kin) to an absolute path. Git answers relative to the checkout for a primary worktree and absolutely for a linked one, and the worktree-private files live in the linked checkout's own Git directory rather than the common one, so resolution belongs to Git and the absolute form belongs here.
func (*Repo) HeadExists ¶ added in v0.30.0
HeadExists reports whether the repository has a born HEAD (at least one commit). A fresh repository whose immediate symbolic HEAD target is absent reports false without error. Missing refs deeper in a symbolic chain and corrupt or cyclic chains are errors. It reads the repository only.
func (*Repo) HeadHash ¶ added in v0.30.0
HeadHash resolves the current HEAD commit hash without requiring a clean working tree. The final current-state upgrade runs in an integration worktree that carries the applied but uncommitted attestation patches, so it compares HEAD identity against the sealed PreparedHead without a cleanliness check.
func (*Repo) IndexBlobs ¶ added in v0.30.0
IndexBlobs returns sorted stage-0 ordinary and executable blobs from the index. Symlinks and gitlinks have no regular-file content to scan and are ignored. An unmerged or unreadable regular entry makes the snapshot unsafe.
func (*Repo) MergeFastForward ¶ added in v0.30.0
MergeFastForward advances HEAD to rev, refusing anything that would create a commit. It is the integration path for a branch that is strictly ahead.
func (*Repo) MergeNoCommit ¶ added in v0.30.0
MergeNoCommit merges rev into HEAD and stops before committing, leaving the result (or the conflict) visible in the working tree. Divergent integration deliberately hands the outcome back to a person instead of committing it.
func (*Repo) PeelCommit ¶ added in v0.30.0
PeelCommit recursively peels annotated tags and returns a commit or terminal target type.
func (*Repo) RangeBlobs ¶ added in v0.30.0
RangeBlobs returns the before/after regular-blob sets for the transition into the commit rev resolves to: after is that commit's tree, before is its first-parent tree, or nil for a root commit. Merges follow the first parent only, so an ADR status change committed on a branch and merged is still observed at the merge. It reads the repository only.
func (*Repo) RangeChangedPaths ¶ added in v0.30.0
RangeChangedPaths returns paths changed between base and head, rerooted to the handle root, using native Git's --name-only semantics.
func (*Repo) RangeDiffText ¶ added in v0.30.0
RangeDiffText returns unified diff text for base through head. The options pin the b/ destination prefix consumed by repoaudit's parser.
func (*Repo) ResolveCommit ¶ added in v0.30.0
ResolveCommit resolves revision to the full object ID of the commit it names, failing when revision names no commit. The response is length-checked because a caller compares the returned identity against another: a truncated or abbreviated answer would compare unequal against a full one and be read as history having moved.
func (*Repo) Root ¶ added in v0.30.0
Root is the path the handle is anchored at: the directory whose subtree the handle's reads are scoped to, which a consumer joining repository-relative paths back onto disk needs.
func (*Repo) ValidateRefName ¶ added in v0.30.0
ValidateRefName reports whether name is well formed as a branch name, which is the question every caller here asks. It validates the full refs/heads/ form rather than passing --branch, and the difference is not cosmetic: the bare name form rejects a one-level name like "main" that is a perfectly valid branch, while --branch answers an invalid name with exit 128 instead of the exit 1 that means "no", so a malformed name would surface as a fault rather than a negative. Qualifying the name asks the branch question and keeps the exit-0/1 contract the probe helper depends on.
func (*Repo) VerifySSH ¶ added in v0.30.0
func (r *Repo) VerifySSH(ctx context.Context, id string, signers []commitpolicy.Signer) (verdict commitpolicy.SignatureVerdict, retErr error)
VerifySSH verifies one commit through an operation-local allowed-signers file.
func (*Repo) WalkRangeCommits ¶ added in v0.31.0
func (r *Repo) WalkRangeCommits(ctx context.Context, base, head string, visit func(Commit) error) (int, error)
WalkRangeCommits visits commits reachable from head but not from base. The range is always caller-supplied. It returns the number successfully visited; unrelated histories are errors.
func (*Repo) WorkingPaths ¶ added in v0.30.0
WorkingPaths returns tracked HEAD paths that still exist plus nonignored untracked paths, rerooted to the handle's root. A specifically unborn HEAD supplies an empty committed baseline; every other repository, reference, or object error still fails. The root may be an adopted project nested inside a containing monorepo; paths outside that project are excluded. Deleted and nested-repository files are excluded by go-git's worktree status semantics; ignored files are excluded by those semantics plus the injected global and system excludes (globalExcludePatterns).
func (*Repo) WorktreeAdd ¶ added in v0.30.0
WorktreeAdd registers a new checkout at path on a newly created branch starting at base. It is the one entrypoint that creates a branch: the creation is inseparable from the registration Git performs with it.
func (*Repo) WorktreeList ¶ added in v0.30.0
func (r *Repo) WorktreeList(ctx context.Context) ([]WorktreeRegistration, error)
WorktreeList returns the repository's registrations as seen from this handle.
func (*Repo) WorktreePrune ¶ added in v0.30.0
WorktreePrune drops registrations whose checkout is already gone. The immediate expiry is deliberate: a caller prunes only after proving the specific path absent, so honouring a grace period would leave the proven registration behind. Git prunes an absent checkout without the flag in the shapes the contract suite builds, so the flag is a guarantee against Git's default grace period rather than something a test here distinguishes.
type ResidentName ¶ added in v0.30.0
type ResidentName string
ResidentName is the closed set of repository-wide awf resident roots.
const ( ResidentEfforts ResidentName = "efforts" ResidentWorktrees ResidentName = "worktrees" ResidentEffortArchive ResidentName = "effort-archive" )
type TreeEntry ¶ added in v0.30.0
TreeEntry is one committed project's path and preserved Git blob mode. It carries tree metadata only, never blob content.
type WorktreeRegistration ¶ added in v0.30.0
type WorktreeRegistration struct {
Path string
HEAD string
Branch string
Detached bool
Bare bool
Prunable bool
}
WorktreeRegistration is one native-Git worktree registration.
func ListWorktreeRegistrations ¶ added in v0.30.0
func ListWorktreeRegistrations(ctx context.Context, invokingRoot string) ([]WorktreeRegistration, error)
ListWorktreeRegistrations returns the repository's native-Git registrations without consulting or scanning filesystem ancestors.