Documentation
¶
Index ¶
- Constants
- Variables
- func CompareAndSwapRef(ctx context.Context, repoRoot string, refName plumbing.ReferenceName, ...) error
- func EnvWithoutRepoOverrides() []string
- func HashWorktreeFiles(ctx context.Context, worktreeRoot string, paths []string) (map[string]plumbing.Hash, error)
- func OpenCurrent(ctx context.Context) (*git.Repository, error)
- func OpenPath(repoRoot string) (*git.Repository, error)
- func ResolveCommonGitPath(dotGitPath string) (string, error)
- func ResolveDotGitPath(repoRoot string) (string, error)
- func SetStatusBudgetBreachedForTesting(breached bool)
- func Status(_ context.Context, repo *git.Repository) (git.Status, error)
- func StatusWithBudget(ctx context.Context, repo *git.Repository) (git.Status, error)
- type WorktreeMetadata
Constants ¶
const StatusWalkBudget = 20 * time.Second
StatusWalkBudget bounds the wall-clock time of one worktree status read on the agent-hook capture paths — the go-git walk in StatusWithBudget and the first-checkpoint `git status` subprocess in the checkpoint store. Agents time out their hooks at roughly 60s (Claude Code's default), but a timed-out hook PROCESS is not killed — an unbounded walk over a pathological worktree (e.g. a stray `git init` in $HOME with no .gitignore) has been observed grinding for hours at gigabytes of RSS after the agent gave up. 20s is chosen as far beyond any healthy repository (a warm walk over a large working set finishes in seconds) while leaving the remaining ~40s of the agent's timeout for the rest of the capture path — transcript copy, tree building, state writes — so the hook still degrades gracefully and exits instead of being orphaned.
const WorktreeContentHashBudget = 5 * time.Second
WorktreeContentHashBudget bounds native Git clean-filter processing on the post-commit hook path. A broken or hanging custom filter must not leave the hook process blocked indefinitely.
Variables ¶
var ( // ErrRefCASConflict means the ref no longer has the expected old value. ErrRefCASConflict = errors.New("git reference changed during compare-and-swap") // ErrRefLocked means native Git could not acquire the ref lock. ErrRefLocked = errors.New("git reference lock is unavailable") // ErrRefSymbolic means the requested CAS target is a symbolic reference. ErrRefSymbolic = errors.New("git reference is symbolic") )
var ErrStatusBudgetExceeded = errors.New("worktree status walk exceeded time budget")
ErrStatusBudgetExceeded reports that a worktree status walk was abandoned because it exceeded StatusWalkBudget. Capture is fail-open: hook-path callers must treat this like any other status failure — warn and continue with transcript-derived data — never fail the hook.
var ErrWorktreeMetadataNotFound = errors.New("worktree Git metadata not found")
ErrWorktreeMetadataNotFound reports that an explicit worktree root has no .git entry. Repository opening uses it to distinguish a possible bare repository from broken worktree metadata.
Functions ¶
func CompareAndSwapRef ¶ added in v0.10.6
func CompareAndSwapRef( ctx context.Context, repoRoot string, refName plumbing.ReferenceName, newHash, expectedHash plumbing.Hash, ) error
CompareAndSwapRef atomically updates a direct ref through native Git and rejects symbolic refs. ZeroHash as expectedHash requires that refName does not exist.
func EnvWithoutRepoOverrides ¶ added in v0.10.3
func EnvWithoutRepoOverrides() []string
EnvWithoutRepoOverrides returns the current environment minus git's repo-selector variables (GIT_DIR, GIT_WORK_TREE, GIT_INDEX_FILE), so a git subprocess resolves its repository from cmd.Dir as the call site intends.
Use this for any git subprocess that can run inside a git hook and that names its target with cmd.Dir or `-C`. Inheriting these variables makes the child silently operate on the hook's repository instead: `git -C <other> rev-parse` reports the hook's repo, and an index-touching command reads and writes whatever GIT_INDEX_FILE names.
Deliberately not applied to user-invoked commands that operate on the current directory (`entire status`, `entire doctor`, `entire review`): there a GIT_DIR the user exported in their own shell is an instruction, not contamination.
func HashWorktreeFiles ¶ added in v0.11.0
func HashWorktreeFiles( ctx context.Context, worktreeRoot string, paths []string, ) (map[string]plumbing.Hash, error)
HashWorktreeFiles returns the Git blob hash of each regular working-tree file after applying Git's path-specific clean filters. Git hash-object follows symlinks, so callers comparing Git symlink blobs must handle those separately. Large path sets are split across commands so an oversized argv cannot fail before Git inspects anything.
The paths must be repository-relative. They are file operands, not pathspecs, so names containing pathspec magic are interpreted literally. The returned map can contain successful hashes alongside a non-nil error; callers can retain filter-aware results and degrade only the files Git could not hash.
func OpenCurrent ¶
func OpenCurrent(ctx context.Context) (*git.Repository, error)
OpenCurrent opens the current git worktree with object alternates enabled. The caller owns the returned repository and must close it.
A worktree root that will not resolve is an error, not a reason to open the current directory. This used to fall back to ".", which is a different repository whenever the two disagree, and go-git disagrees with git in exactly the cases that made the resolution fail:
- git exports GIT_DIR and GIT_WORK_TREE to the hooks it runs, and paths.WorktreeRoot honours them. OpenPath(".") cannot see them, so a hook running for repo A whose git lookup failed opened repo B, the unrelated repository it happened to be sitting in. Verified.
- git refuses a repository whose ownership fails its safe.directory check, and refuses a .git it cannot parse. go-git applies neither check, so the fallback opened repositories the user's own git declines to touch.
func OpenPath ¶
func OpenPath(repoRoot string) (*git.Repository, error)
OpenPath opens a git repository with object alternates enabled. The caller owns the returned repository and must close it.
func ResolveCommonGitPath ¶ added in v0.10.3
ResolveCommonGitPath resolves the shared Git directory for a resolved .git directory. An empty result means the repository has no commondir file.
func ResolveDotGitPath ¶ added in v0.10.3
ResolveDotGitPath resolves the .git entry for a worktree without opening the repository. Callers that need Git metadata should use this shared resolver.
func SetStatusBudgetBreachedForTesting ¶ added in v0.10.3
func SetStatusBudgetBreachedForTesting(breached bool)
SetStatusBudgetBreachedForTesting overrides the process-local breach latch so tests can exercise budget-breach degradation without a slow walk.
func Status ¶ added in v0.10.0
Status is the single entry point for reading go-git worktree status; the forbidigo rule in .golangci.yaml enforces this and names this signature, so the context parameter is part of that contract and is where cancellation or a perf span would attach.
Worktree.Status() walks the worktree, so its cost scales with working-set size rather than with the size of the change being inspected — it is the most expensive git read on the hook paths. Avoid calling it more than once per hook.
func StatusWithBudget ¶ added in v0.10.3
StatusWithBudget is Status bounded by StatusWalkBudget, for agent-hook capture paths. go-git's Worktree.Status is not context-cancellable, so on breach the walk goroutine is abandoned — it dies with the short-lived hook process, which is the point — and the returned error wraps ErrStatusBudgetExceeded so callers' warn-and-continue degrade paths apply. Paths where a user is actively waiting on a command (review via review_target.go, and `session adopt` via detectFileChangesUnbounded) keep calling Status directly.
Types ¶
type WorktreeMetadata ¶ added in v0.10.6
WorktreeMetadata contains Git directory facts for one explicit worktree root. Paths are cleaned and absolute but retain their lexical spelling.
func ResolveWorktreeMetadata ¶ added in v0.10.6
func ResolveWorktreeMetadata(worktreeRoot string) (WorktreeMetadata, error)
ResolveWorktreeMetadata resolves filesystem metadata for an explicit worktree root. It does not discover a root, inspect Git environment variables, run Git, cache results, or decide caller policy.