Documentation
¶
Overview ¶
Package git provides low-level Git operations, including repository access, branch operations, commit information, PR operations, and metadata management.
Package git provides low-level Git operations.
Operations that support multiple inputs expose a single plural API. Collect known inputs at the caller and pass them together; calling the plural method repeatedly in a loop still incurs repeated I/O. Implementations choose the appropriate path for zero, one, or many inputs.
ReadRevisions and ReadCommitInfo return ReadResults keyed by the requested input. MetadataStore owns shared, local, and stack metadata persistence and returns shared/local metadata with the exact ref versions read alongside it. Get and One inspect those results without I/O. Missing revisions are errors; missing metadata yields empty metadata. Duplicate read inputs share one result.
CreateBlobs returns SHAs in input order, including duplicate inputs. UpdateRefs applies one atomic transaction with optional per-ref expectations. PushBranches returns per-branch outcomes and permits partial success. An empty input list performs no writes, fetches, pushes, or merges.
Package git provides a wrapper around the git CLI for repository operations.
Index ¶
- Constants
- Variables
- func BranchFetchRefspec(remote, branch string) string
- func CaseMismatchHint(name string, branchNames []string) string
- func GetCurrentDate() string
- func GetGitCommonDir(repoRoot string) string
- func GetGitDir(repoRoot string) string
- func IsLocalChangesError(err error) bool
- func IsMainWorktree(worktreePath WorktreePath, repoRoot string) bool
- func LocalMetadataRefName(branchName string) string
- func MetadataRefName(branchName string) string
- func ObjectContent(objects map[string]BatchObject, err error) (string, error)
- func One[T any](values []T, err error) (T, error)
- func ResolveBranchNameCase(name string, branchNames []string) string
- func ShortRevision(rev string, maxLen int) string
- func StackMetaRefName(stackID string) string
- func WithRemoteOperationTimeout(parent context.Context) (context.Context, context.CancelFunc)
- type BatchObject
- type BranchReader
- type BranchRefUpdate
- type BranchType
- type BranchWriter
- type CherryPickOperations
- type CommandError
- type CommitInfo
- type CommitLogFormat
- type CommitMetadata
- type CommitNode
- type CommitOptions
- type CommitReader
- type CommitWriter
- type Commits
- type CommittedMetadata
- type ConfigStore
- func (c *ConfigStore) Add(key, value string) error
- func (c *ConfigStore) Exists(key string) bool
- func (c *ConfigStore) Get(key string) (string, error)
- func (c *ConfigStore) GetAll(key string) ([]string, error)
- func (c *ConfigStore) GetBool(key string) (bool, error)
- func (c *ConfigStore) GetBoolWithDefault(key string, defaultValue bool) bool
- func (c *ConfigStore) GetInt(key string) (int, error)
- func (c *ConfigStore) GetIntWithDefault(key string, defaultValue int) int
- func (c *ConfigStore) Set(key, value string) error
- func (c *ConfigStore) SetBool(key string, value bool) error
- func (c *ConfigStore) SetInt(key string, value int) error
- func (c *ConfigStore) Unset(key string) error
- type DebugLogger
- type DiffFormat
- type DiffOperations
- type DiffReadMode
- type DiffSummary
- type Hunk
- func (h Hunk) CanSplit() bool
- func (h Hunk) Header() string
- func (h Hunk) LineCounts() (added, removed int)
- func (h Hunk) NewFileContent() string
- func (h Hunk) Overlaps(other Hunk) bool
- func (h Hunk) Preview(maxLines int) (preview string, totalLines int, hasMore bool)
- func (h Hunk) Split() (Hunks, error)
- type HunkTarget
- type Hunks
- type LocalMeta
- type LocalMetaMap
- type LockReason
- type MergeOperations
- type MergeOptions
- type MergedParent
- type Meta
- func (m *Meta) GetBranchType() BranchType
- func (m *Meta) GetLastModifiedAt() *time.Time
- func (m *Meta) GetLastModifiedBy() *ModifiedBy
- func (m *Meta) GetLocalOnlyHash() *string
- func (m *Meta) GetLockReason() LockReason
- func (m *Meta) GetMergedDownstack() []MergedParent
- func (m *Meta) GetParentBranchName() *string
- func (m *Meta) GetParentBranchRevision() *string
- func (m *Meta) GetPrInfo() *PrInfoPersistence
- func (m *Meta) GetScope() *string
- func (m *Meta) GetStackID() *string
- func (m Meta) MarshalJSON() ([]byte, error)
- func (m *Meta) UnmarshalJSON(data []byte) error
- func (m *Meta) WithBranchType(v BranchType) *Meta
- func (m *Meta) WithLastModifiedAt(v *time.Time) *Meta
- func (m *Meta) WithLastModifiedBy(v *ModifiedBy) *Meta
- func (m *Meta) WithLocalOnlyHash(v *string) *Meta
- func (m *Meta) WithLockReason(v LockReason) *Meta
- func (m *Meta) WithMergedDownstack(v []MergedParent) *Meta
- func (m *Meta) WithParentBranchName(v *string) *Meta
- func (m *Meta) WithParentBranchRevision(v *string) *Meta
- func (m *Meta) WithPrInfo(v *PrInfoPersistence) *Meta
- func (m *Meta) WithScope(v *string) *Meta
- func (m *Meta) WithStackID(v *string) *Meta
- type MetaFields
- type MetadataBackend
- type MetadataCacheSummary
- type MetadataReadResults
- type MetadataRecord
- type MetadataStore
- func (r *MetadataStore) ClearMetadataCache()
- func (r *MetadataStore) DeleteMetadata(ctx context.Context, branchName string) error
- func (r *MetadataStore) GetStackMetaRefSHA(ctx context.Context, stackID string) string
- func (r *MetadataStore) InvalidateMetadata(branchNames ...string)
- func (r *MetadataStore) ListMetadata(ctx context.Context) (map[string]string, error)
- func (r *MetadataStore) ListStackMetas(ctx context.Context) (map[string]string, error)
- func (r *MetadataStore) MetadataCacheStats() MetadataCacheSummary
- func (r *MetadataStore) ReadLocalMetadata(ctx context.Context, branchNames ...string) MetadataReadResults[*LocalMeta]
- func (r *MetadataStore) ReadMetadata(ctx context.Context, branchNames ...string) MetadataReadResults[*Meta]
- func (r *MetadataStore) ReadStackMeta(ctx context.Context, stackID string) (*StackMeta, error)
- func (r *MetadataStore) RecordCommitted(tier MetadataTier, records ...CommittedMetadata)
- func (r *MetadataStore) RenameMetadata(ctx context.Context, oldName, newName string) error
- func (r *MetadataStore) ResetMetadataCacheStats()
- func (r *MetadataStore) SetLogger(logger DebugLogger)
- func (r *MetadataStore) WriteBlobs(ctx context.Context, values ...any) ([]string, error)
- func (r *MetadataStore) WriteLocalMetadata(ctx context.Context, branchName string, meta *LocalMeta) error
- func (r *MetadataStore) WriteLocalMetadataBlobs(ctx context.Context, metas []*LocalMeta) ([]string, error)
- func (r *MetadataStore) WriteMetadata(ctx context.Context, branchName string, meta *Meta) error
- func (r *MetadataStore) WriteMetadataBlobs(ctx context.Context, metas []*Meta) ([]string, error)
- func (r *MetadataStore) WriteStackMeta(ctx context.Context, stackID string, meta *StackMeta) error
- func (r *MetadataStore) WriteStackMetaBlob(ctx context.Context, meta *StackMeta) (string, error)
- type MetadataTier
- type ModifiedBy
- type ObjectOperations
- type PRNumber
- type PRState
- type PatchApplyMode
- type PatchOperations
- type PathOperations
- type PrInfoPersistence
- type PullResult
- type PushLeaseMode
- type PushOptions
- type PushResults
- type PushSpec
- type ReadResult
- type ReadResults
- func (r ReadResults[T]) All() iter.Seq2[string, ReadResult[T]]
- func (r ReadResults[T]) Errs() []error
- func (r *ReadResults[T]) Fail(name string, err error)
- func (r ReadResults[T]) Failures() map[string]error
- func (r ReadResults[T]) Get(name string) (T, error)
- func (r ReadResults[T]) One() (T, error)
- func (r *ReadResults[T]) Record(name string, value T, err error)
- func (r *ReadResults[T]) Set(name string, value T)
- func (r ReadResults[T]) Split() (map[string]T, map[string]error)
- func (r ReadResults[T]) Values() map[string]T
- func (r ReadResults[T]) ValuesAndErrors() (map[string]T, []error)
- type RebaseOperations
- type RebaseOutcome
- type RebaseResult
- type RebaseSpec
- type RecentCommit
- type RecentCommitKind
- type RecentCommits
- type RefDecoration
- type RefOperations
- type RefUpdate
- type RemoteBranchSHAs
- type RemoteOperations
- type RemoteRepository
- type RepositoryReader
- type RepositoryWriter
- type ResetOperations
- type RevRange
- type Runner
- type SquashMergeCache
- type StackDescription
- type StackMeta
- type StagingOperations
- type StagingOptions
- type StashApplyMode
- type StashCapture
- type StashOperations
- type StatusOperations
- type Version
- type Worktree
- type WorktreeCheckoutMode
- type WorktreeDetachMode
- type WorktreeHeldError
- type WorktreeList
- type WorktreeMeta
- type WorktreeName
- type WorktreeOperations
- type WorktreePath
- type WorktreeRegistration
- type WorktreeRegistryOperations
- type WorktreeStatus
Constants ¶
const ( // MetadataRefPrefix is the prefix for Git refs where branch metadata is stored MetadataRefPrefix = "refs/stackit/metadata/" // LocalMetadataRefPrefix is the prefix for Git refs where local-only branch metadata is stored LocalMetadataRefPrefix = "refs/stackit/local-metadata/" )
const ( // StackMetaRefPrefix is the prefix for Git refs where stack metadata is stored StackMetaRefPrefix = "refs/stackit/stacks/" // RemoteStackMetaRefPrefix is the prefix for remote stack metadata refs (fetched from remote) RemoteStackMetaRefPrefix = "refs/stackit/remote-stacks/" )
const CommandWaitDelay = 10 * time.Second
CommandWaitDelay bounds how long we wait for a killed git/gh subprocess to release its stdio pipes before force-closing them. Without it, a `git fetch` can spawn an `ssh` grandchild that inherits the captured stdout/stderr pipe; when the context deadline kills git, ssh keeps the pipe open and cmd.Run() blocks indefinitely — the command times out but never returns, which is the hang-until-reboot behind issue #1330. Setting WaitDelay makes Go force-close the pipes shortly after the kill so Run() always returns.
const DefaultCommandTimeout = 5 * time.Minute
DefaultCommandTimeout is the default timeout for git commands
const DefaultRemote = "origin"
DefaultRemote is the default name for the remote repository
const DefaultRemoteOperationTimeout = 5 * time.Minute
DefaultRemoteOperationTimeout bounds explicit remote operations launched by commands when the parent command context does not already carry a deadline.
const MaxRerereContinueIterations = 1000
MaxRerereContinueIterations caps the auto-continue loop so a pathological rebase cannot spin forever. Real rebases finish in far fewer iterations.
const WorktreePathRefPrefix = "refs/stackit/worktree-paths/"
WorktreePathRefPrefix is a reverse index from canonical worktree path to its anchor registration. Keeping this alongside WorktreeRefPrefix lets a single update-ref transaction enforce both directions of the ownership invariant.
const WorktreeRefPrefix = "refs/stackit/worktrees/"
WorktreeRefPrefix is the prefix for Git refs where worktree metadata is stored (local-only)
Variables ¶
var ErrStaleRemoteInfo = errors.New("stale info")
ErrStaleRemoteInfo indicates that a push failed because the remote has changed
var MinimumGitVersion = Version{Major: 2, Minor: 36}
MinimumGitVersion is the oldest Git that can run stackit's stack operations. ListWorktrees needs `git worktree list -z`, which arrived in 2.36, and every ref-moving command inspects worktrees before it moves anything.
Functions ¶
func BranchFetchRefspec ¶ added in v0.19.0
BranchFetchRefspec builds the refspec used to fetch a remote branch into its remote-tracking ref. The leading '+' forces the update so a force-pushed remote branch (whose new tip is not a descendant of the previously fetched tip) still updates refs/remotes/<remote>/<branch>, instead of failing the fetch as a non-fast-forward update. This mirrors the '+' in Git's default "+refs/heads/*:refs/remotes/origin/*" fetch refspec.
func CaseMismatchHint ¶ added in v0.24.0
CaseMismatchHint returns a parenthetical explaining that name is absent from branchNames only because of casing, or "" when casing is not the problem. Turns "branch X does not exist" — reported for a branch the user can see — into a message that names both spellings.
func GetCurrentDate ¶
func GetCurrentDate() string
GetCurrentDate returns the current date and time in yyyyMMddHHmmss format in UTC
func GetGitCommonDir ¶
GetGitCommonDir resolves the shared git directory for a repository. In a linked worktree this follows the commondir pointer back to the main repository's .git directory.
func GetGitDir ¶
GetGitDir resolves the actual git directory for a repository. In worktrees, .git is a file pointing to the real git directory, so we need to use git rev-parse to get the correct path.
This returns the worktree-specific git directory (use GetGitCommonDir for shared config).
func IsLocalChangesError ¶
IsLocalChangesError returns true if the error indicates that local changes would be overwritten
func IsMainWorktree ¶ added in v0.22.0
func IsMainWorktree(worktreePath WorktreePath, repoRoot string) bool
IsMainWorktree reports whether worktreePath is the repo's main worktree (repoRoot), resolving symlinks on both sides for comparison (e.g. /var vs /private/var on macOS).
Only use this when repoRoot is known to be the main working tree. An engine constructed inside a temporary worktree reports that worktree as its repo root, which makes this answer "no" for the user's actual main checkout — prefer WorktreeList.IsMain, which reads the answer from git instead of trusting the caller's idea of where the repo lives.
func LocalMetadataRefName ¶
LocalMetadataRefName returns the full ref name for a branch's local metadata.
func MetadataRefName ¶
MetadataRefName returns the full ref name for a branch's metadata.
func ObjectContent ¶ added in v0.28.0
func ObjectContent(objects map[string]BatchObject, err error) (string, error)
ObjectContent extracts the content of a single requested object. It only inspects results returned by ReadObjects; it never performs Git I/O.
func One ¶ added in v0.28.0
One extracts the sole value from a one-input write. It only handles the returned values and error; it never performs I/O or repeats the write.
func ResolveBranchNameCase ¶ added in v0.24.0
ResolveBranchNameCase reconciles a branch name reported by HEAD with the casing the ref actually carries in refs/heads.
On case-insensitive filesystems (macOS and Windows defaults) loose refs `refs/heads/Claude/x` and `refs/heads/claude/x` are the same file, so whichever casing created the directory first wins on disk. HEAD, however, stores the name verbatim as requested at checkout time, so `git symbolic-ref --short HEAD` can echo back a casing that for-each-ref never reports. Every lookup of the current branch against the branch list then misses, and stackit reports the branch you are standing on as nonexistent.
The exact match always wins, so this is a no-op on case-sensitive filesystems. The case-insensitive fallback engages only when the exact name is absent from branchNames and exactly one candidate differs by case alone — a case-insensitive filesystem cannot hold two such refs, so a unique match there is the ref HEAD meant.
Caveat: on a case-sensitive filesystem an unborn branch (`git checkout --orphan Feature`) whose name differs only in case from an existing branch resolves to that existing branch. Harmless in practice, and the alternative costs a git call on every current-branch read.
func ShortRevision ¶ added in v0.30.1
ShortRevision returns a shortened version of a git revision hash. Returns at most maxLen characters, defaulting to 7 if maxLen <= 0.
func StackMetaRefName ¶
StackMetaRefName returns the full ref name for a stack's metadata. Use this helper instead of concatenating StackMetaRefPrefix directly to ensure consistent ref name construction across all stack metadata operations.
func WithRemoteOperationTimeout ¶ added in v0.30.1
WithRemoteOperationTimeout applies the default remote-operation timeout only when the parent context has no deadline. The returned cancel function should always be called by the caller.
Types ¶
type BatchObject ¶ added in v0.25.0
BatchObject is one object's content together with the SHA the ref resolved to. Callers that intend to write the ref back keep the SHA so they can detect another process having written it in between.
type BranchReader ¶
type BranchReader interface {
GetCurrentBranch(ctx context.Context) (string, error)
GetAllBranchNames(ctx context.Context) ([]string, error)
GetCurrentBranchOrSHA(ctx context.Context) (string, error)
}
BranchReader provides read access to branch information.
type BranchRefUpdate ¶ added in v0.29.0
type BranchRefUpdate struct {
// Branch is the short branch name (without refs/heads/).
Branch string
// NewRevision is resolved to the SHA the branch moves to.
NewRevision string
// ExpectedOld is the SHA the branch must still name; required.
ExpectedOld string
}
BranchRefUpdate is a compare-and-swap move of one local branch. Unlike RefUpdate it names a branch rather than a full ref, accepts any revision for the new tip, and always requires the expected old SHA.
type BranchType ¶
type BranchType string
BranchType indicates the type of branch
const ( BranchTypeUser BranchType = "user" // Normal stacked branch BranchTypeUtility BranchType = "utility" // Created by st merge --consolidate or other internal tasks BranchTypeWorktreeAnchor BranchType = "worktree-anchor" // Anchor branch for worktree, has no commits )
Branch types
type BranchWriter ¶
type BranchWriter interface {
CheckoutBranch(ctx context.Context, branchName string) error
CheckoutBranchForce(ctx context.Context, branchName string) error
CheckoutDetached(ctx context.Context, revision string) error
CreateAndCheckoutBranch(ctx context.Context, branchName string) error
CreateBranch(ctx context.Context, branchName, startPoint string) error
CreateBranchForce(ctx context.Context, branchName, revision string) error
DeleteBranch(ctx context.Context, branchName string) error
RenameBranch(ctx context.Context, oldName, newName string) error
UpdateBranchRef(ctx context.Context, branchName, revision string) error
// UpdateBranchRefCAS moves a branch only if it still names
// update.ExpectedOld. Callers that prepared commits from a detached
// snapshot use this to avoid overwriting concurrent work from another
// worktree.
UpdateBranchRefCAS(ctx context.Context, update BranchRefUpdate) error
}
BranchWriter handles branch lifecycle operations.
type CherryPickOperations ¶
type CherryPickOperations interface {
CherryPick(ctx context.Context, commitSHA, onto string) (string, error)
CherryPickSimple(ctx context.Context, commitSHA string) error
CherryPickAbort(ctx context.Context) error
}
CherryPickOperations handles cherry-pick operations.
type CommandError ¶
CommandError represents an error from a git command execution
func NewCommandError ¶
func NewCommandError(command string, args []string, stdout, stderr string, err error) *CommandError
NewCommandError creates a new CommandError
func (*CommandError) Error ¶
func (e *CommandError) Error() string
func (*CommandError) Unwrap ¶
func (e *CommandError) Unwrap() error
type CommitInfo ¶ added in v0.25.0
CommitInfo holds a branch tip commit's author date and author name.
type CommitLogFormat ¶ added in v0.29.0
type CommitLogFormat int
CommitLogFormat selects how ShowCommits renders each commit in a range.
const ( // CommitLogOneline renders "<short sha> - <subject>" per commit. CommitLogOneline CommitLogFormat = iota // CommitLogPatch renders each commit with its full patch (-p). CommitLogPatch // CommitLogStat renders each commit with a per-file --stat summary. CommitLogStat )
type CommitMetadata ¶ added in v0.28.0
type CommitMetadata struct {
SHA string
ShortSHA string
Subject string
Parents []string
AuthorName string
AuthorEmail string
AuthorDate string
Message string
}
CommitMetadata contains the original identity and topology needed to replay a commit.
type CommitNode ¶ added in v0.28.0
CommitNode is identity/topology only; it cannot be mistaken for display data.
type CommitOptions ¶
type CommitOptions struct {
Message string
Amend bool
NoEdit bool
Edit bool
Verbose int
ResetAuthor bool
NoVerify bool
}
CommitOptions contains options for creating a commit
type CommitReader ¶
type CommitReader interface {
ReadRevisions(ctx context.Context, refs ...string) ReadResults[string]
ReadCommitInfo(ctx context.Context, refs ...string) ReadResults[CommitInfo]
ReadCommitRanges(ctx context.Context, ranges ...RevRange) ReadResults[[]CommitMetadata]
ReadCommitNodes(ctx context.Context, ranges ...RevRange) ReadResults[[]CommitNode]
ReadCommits(ctx context.Context, refs ...string) ReadResults[CommitMetadata]
ReadAncestry(ctx context.Context, ranges ...RevRange) ReadResults[bool]
ReadCommitCounts(ctx context.Context, ranges ...RevRange) ReadResults[int]
GetRecentCommits(ctx context.Context, branchName string, count int) ([]RecentCommit, error)
GetRecentCommitsInRange(ctx context.Context, revRange string) ([]RecentCommit, error)
GetCommitTemplate(ctx context.Context) (string, error)
}
CommitReader provides read access to commit and revision information.
type CommitWriter ¶
type CommitWriter interface {
Commit(ctx context.Context, message string, verbose int, noVerify bool) error
CommitWithOptions(ctx context.Context, opts CommitOptions) error
CommitAmendNoEdit(ctx context.Context) error
}
CommitWriter handles commit creation and modification.
type Commits ¶ added in v0.28.0
type Commits []CommitMetadata
Commits keeps identity, message and authorship together until a consumer projects the particular fields it needs.
func (Commits) Messages ¶ added in v0.28.0
Messages returns nonempty, trimmed messages in history order.
type CommittedMetadata ¶ added in v0.28.0
type CommittedMetadata struct {
Branch string
// SHA is the blob the ref now holds, or "" when the write deleted it.
SHA string
// Meta is the value written; used for the shared tier's value cache and
// ignored for the local tier (whose values are never cached).
Meta *Meta
}
CommittedMetadata describes one metadata ref this process just wrote through the backend directly, bypassing the store.
type ConfigStore ¶
type ConfigStore struct {
// contains filtered or unexported fields
}
ConfigStore provides typed access to git config. Implemented via direct `git config` invocations rather than parsing the config file in process.
func NewConfigStore ¶
func NewConfigStore(repoRoot string) *ConfigStore
NewConfigStore creates a new ConfigStore for the given repository root.
func (*ConfigStore) Add ¶
func (c *ConfigStore) Add(key, value string) error
Add adds a value to a multi-value config key.
func (*ConfigStore) Exists ¶
func (c *ConfigStore) Exists(key string) bool
Exists checks if a config key exists.
func (*ConfigStore) Get ¶
func (c *ConfigStore) Get(key string) (string, error)
Get retrieves a single config value, reading git's merged config (system → global → local) — the same precedence `git config --get` applies when invoked from inside the repo. Returns empty string if the key isn't set in any scope. Use this for keys whose canonical home is often the user's global config (e.g. user.name, user.email).
func (*ConfigStore) GetAll ¶
func (c *ConfigStore) GetAll(key string) ([]string, error)
GetAll retrieves all values for a multi-value config key. Returns nil if the key doesn't exist or has a single empty value.
func (*ConfigStore) GetBool ¶
func (c *ConfigStore) GetBool(key string) (bool, error)
GetBool retrieves a boolean config value. Returns false and no error if the key doesn't exist.
func (*ConfigStore) GetBoolWithDefault ¶
func (c *ConfigStore) GetBoolWithDefault(key string, defaultValue bool) bool
GetBoolWithDefault retrieves a boolean config value with a default.
func (*ConfigStore) GetInt ¶
func (c *ConfigStore) GetInt(key string) (int, error)
GetInt retrieves an integer config value. Returns 0 and no error if the key doesn't exist.
func (*ConfigStore) GetIntWithDefault ¶
func (c *ConfigStore) GetIntWithDefault(key string, defaultValue int) int
GetIntWithDefault retrieves an integer config value with a default.
func (*ConfigStore) Set ¶
func (c *ConfigStore) Set(key, value string) error
Set sets a config value in local git config.
func (*ConfigStore) SetBool ¶
func (c *ConfigStore) SetBool(key string, value bool) error
SetBool sets a boolean config value.
func (*ConfigStore) SetInt ¶
func (c *ConfigStore) SetInt(key string, value int) error
SetInt sets an integer config value.
func (*ConfigStore) Unset ¶
func (c *ConfigStore) Unset(key string) error
Unset removes all values for a config key. Does not return an error if the key doesn't exist.
type DebugLogger ¶
DebugLogger is an interface for logging messages from the git layer. Despite its name, it carries both debug and informational events; the latter is used for instrumentation lines (cache stats, batch-load timings) that should be visible at the default log level.
type DiffFormat ¶ added in v0.29.0
type DiffFormat int
DiffFormat selects how ShowDiff renders the difference between two trees.
const ( // DiffFormatPatch renders the full patch. DiffFormatPatch DiffFormat = iota // DiffFormatStat renders a per-file --stat summary. DiffFormatStat )
type DiffOperations ¶
type DiffOperations interface {
GetMergeBase(ctx context.Context, rev1, rev2 string) (string, error)
IsAncestor(ctx context.Context, ancestor, descendant string) (bool, error)
IsMerged(ctx context.Context, branchName, target string) (bool, error)
IsSquashMerged(ctx context.Context, branchName, target string, cache *SquashMergeCache) (bool, error)
GetMergedBranches(ctx context.Context, target string) (map[string]bool, error)
ReadDiffs(ctx context.Context, mode DiffReadMode, ranges ...RevRange) ReadResults[DiffSummary]
ShowDiff(ctx context.Context, rr RevRange, format DiffFormat) (string, error)
ShowCommits(ctx context.Context, rr RevRange, format CommitLogFormat) (string, error)
GetStagedDiff(ctx context.Context, files ...string) (string, error)
GetUnstagedDiff(ctx context.Context, files ...string) (string, error)
// GetUnstagedDiffBinary is like GetUnstagedDiff but includes full binary
// content (`git diff --binary`) so the result can be reapplied with
// `git apply`.
GetUnstagedDiffBinary(ctx context.Context, files ...string) (string, error)
// GetDiffBetween returns the raw diff between two refs, without color codes.
// This is suitable for parsing into hunks.
GetDiffBetween(ctx context.Context, rr RevRange, files ...string) (string, error)
}
DiffOperations provides access to diff and comparison operations.
type DiffReadMode ¶ added in v0.28.0
type DiffReadMode int
DiffReadMode selects the work required by a diff consumer.
const ( // DiffCheckOnly compares trees without walking files or reading blobs. DiffCheckOnly DiffReadMode = iota // DiffNames reads changed paths without computing line counts. DiffNames // DiffStats reads changed paths and additions/deletions (binary files count as zero lines). DiffStats )
type DiffSummary ¶ added in v0.28.0
DiffSummary describes a comparison between two trees. Files are sorted and renames use the destination path, matching git diff --name-only.
type Hunk ¶
type Hunk struct {
File string // File path
OldStart int // Line number in old file (1-indexed)
OldCount int // Number of lines in old file
NewStart int // Line number in new file (1-indexed)
NewCount int // Number of lines in new file
Content string // The actual diff content (including header)
IndexLine string // The index line from the diff (e.g., "index abc123..def456 100644") for --3way merging
Binary bool // True if this represents a binary file change
IsNewFile bool // True if this hunk is for a newly created file
IsDeletedFile bool // True if this hunk is for a deleted file
FileMode string // File mode (e.g., "100644", "100755") for new/deleted files
}
Hunk represents a single hunk of changes in a diff
func GenerateNewFileHunk ¶
GenerateNewFileHunk creates a synthetic hunk for an untracked file. This allows new files to be included in hunk-based splitting.
func (Hunk) CanSplit ¶ added in v0.22.0
CanSplit returns true if the hunk has context lines between changes, meaning it can be split into multiple smaller hunks. A hunk is splittable only when there's at least one context line that separates two distinct groups of changes (additions/deletions).
func (Hunk) LineCounts ¶ added in v0.22.0
LineCounts returns the number of added and removed lines in a hunk
func (Hunk) NewFileContent ¶ added in v0.22.0
NewFileContent extracts the file content from a new file hunk. It parses the unified diff format and returns only the added lines (without the + prefix). Respects the "\ No newline at end of file" marker to preserve files without trailing newlines.
func (Hunk) Overlaps ¶ added in v0.22.0
Overlaps reports whether two hunks have overlapping line ranges. It includes a safety margin to account for git context lines.
type HunkTarget ¶
type HunkTarget struct {
Hunk Hunk
CommitSHA string
CommitIndex int // Index in the commit list (0 = newest)
}
HunkTarget represents a hunk and its target commit
type Hunks ¶ added in v0.22.0
type Hunks []Hunk
Hunks is an ordered collection of diff hunks.
func ParseDiffOutput ¶
ParseDiffOutput parses a diff output into structured hunks
type LocalMeta ¶
type LocalMeta struct {
Frozen bool `json:"frozen,omitempty"`
NeedsPRBodyUpdate bool `json:"needsPRBodyUpdate,omitempty"`
// SubmitPending records that a submit pushed this branch but did not
// finish writing its pull request. The push alone makes the branch look
// in sync with the remote, which would otherwise hide the unfinished PR
// write from the next submit. Local because the interrupted submit
// happened on this machine.
SubmitPending bool `json:"submitPending,omitempty"`
}
LocalMeta represents branch metadata that is strictly local and never pushed
type LocalMetaMap ¶ added in v0.22.0
LocalMetaMap is branch name -> local metadata, as returned by the batch local-metadata readers.
func (LocalMetaMap) Get ¶ added in v0.22.0
func (m LocalMetaMap) Get(branchName string) *LocalMeta
Get returns the local metadata for a branch, or nil if absent. Safe to call on a nil map.
type LockReason ¶
type LockReason string
LockReason is an enum for the reason why a branch is locked
const ( // LockReasonNone indicates the branch is not locked LockReasonNone LockReason = "" // LockReasonUser indicates the branch was manually locked by the user LockReasonUser LockReason = "user" // LockReasonConsolidating indicates the branch is being consolidated LockReasonConsolidating LockReason = "consolidating" // LockReasonDraining indicates the branch is being drained (merge drain in progress) LockReasonDraining LockReason = "draining" )
func (LockReason) IsLocked ¶
func (r LockReason) IsLocked() bool
IsLocked returns true if the lock reason indicates the branch is locked
type MergeOperations ¶
type MergeOperations interface {
MergeBranches(ctx context.Context, branches []string, opts MergeOptions) error
IsMergeInProgress(ctx context.Context) bool
MergeAbort(ctx context.Context) error
GetUnmergedFiles(ctx context.Context) ([]string, error)
}
MergeOperations handles merge operations.
type MergeOptions ¶
MergeOptions contains options for merging branches
type MergedParent ¶
type MergedParent struct {
BranchName string `json:"branchName"`
PRNumber *PRNumber `json:"prNumber,omitempty"`
PRState *PRState `json:"prState,omitempty"` // MERGED or CLOSED
}
MergedParent represents a historical parent that was merged or deleted
type Meta ¶
type Meta struct {
// contains filtered or unexported fields
}
Meta represents branch metadata stored in Git refs. Fields are unexported to enforce immutability — use getters to read and With* methods to create modified copies. Construct via NewMeta() or NewMetaFrom(MetaFields{...}).
func NewMetaFrom ¶
func NewMetaFrom(f MetaFields) *Meta
NewMetaFrom constructs a Meta from the given fields.
func (*Meta) GetBranchType ¶
func (m *Meta) GetBranchType() BranchType
GetBranchType returns the branch type.
func (*Meta) GetLastModifiedAt ¶
GetLastModifiedAt returns a copy of the last-modified-at timestamp.
func (*Meta) GetLastModifiedBy ¶
func (m *Meta) GetLastModifiedBy() *ModifiedBy
GetLastModifiedBy returns a shallow copy of the last-modified-by info.
func (*Meta) GetLocalOnlyHash ¶
GetLocalOnlyHash returns the local-only hash.
func (*Meta) GetLockReason ¶
func (m *Meta) GetLockReason() LockReason
GetLockReason returns the lock reason.
func (*Meta) GetMergedDownstack ¶
func (m *Meta) GetMergedDownstack() []MergedParent
GetMergedDownstack returns a copy of the merged downstack history.
func (*Meta) GetParentBranchName ¶
GetParentBranchName returns the parent branch name.
func (*Meta) GetParentBranchRevision ¶
GetParentBranchRevision returns the parent branch revision.
func (*Meta) GetPrInfo ¶
func (m *Meta) GetPrInfo() *PrInfoPersistence
GetPrInfo returns a shallow copy of the PR info.
func (Meta) MarshalJSON ¶
MarshalJSON implements json.Marshaler for Meta.
func (*Meta) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler for Meta.
func (*Meta) WithBranchType ¶
func (m *Meta) WithBranchType(v BranchType) *Meta
WithBranchType returns a new Meta with the branch type set.
func (*Meta) WithLastModifiedAt ¶
WithLastModifiedAt returns a new Meta with the last-modified-at timestamp set.
func (*Meta) WithLastModifiedBy ¶
func (m *Meta) WithLastModifiedBy(v *ModifiedBy) *Meta
WithLastModifiedBy returns a new Meta with the last-modified-by info set.
func (*Meta) WithLocalOnlyHash ¶
WithLocalOnlyHash returns a new Meta with the local-only hash set.
func (*Meta) WithLockReason ¶
func (m *Meta) WithLockReason(v LockReason) *Meta
WithLockReason returns a new Meta with the lock reason set.
func (*Meta) WithMergedDownstack ¶
func (m *Meta) WithMergedDownstack(v []MergedParent) *Meta
WithMergedDownstack returns a new Meta with the merged downstack history set.
func (*Meta) WithParentBranchName ¶
WithParentBranchName returns a new Meta with the parent branch name set.
func (*Meta) WithParentBranchRevision ¶
WithParentBranchRevision returns a new Meta with the parent branch revision set.
func (*Meta) WithPrInfo ¶
func (m *Meta) WithPrInfo(v *PrInfoPersistence) *Meta
WithPrInfo returns a new Meta with the PR info set.
func (*Meta) WithStackID ¶
WithStackID returns a new Meta with the stack ID set.
type MetaFields ¶
type MetaFields struct {
ParentBranchName *string
ParentBranchRevision *string
PrInfo *PrInfoPersistence
Scope *string
LockReason LockReason
BranchType BranchType
LastModifiedBy *ModifiedBy
LastModifiedAt *time.Time
LocalOnlyHash *string
MergedDownstack []MergedParent
StackID *string
}
MetaFields provides exported fields for constructing an immutable Meta. Use with NewMetaFrom to build Meta values in a single expression.
type MetadataBackend ¶ added in v0.28.0
type MetadataBackend interface {
ReadObjects(ctx context.Context, refs ...string) (map[string]BatchObject, error)
CreateBlobs(ctx context.Context, contents ...string) ([]string, error)
UpdateRefs(ctx context.Context, updates []RefUpdate, message string) error
DeleteRefs(ctx context.Context, refs ...string) error
ListRefs(ctx context.Context, prefix string) (map[string]string, error)
ReadRevisions(ctx context.Context, refs ...string) ReadResults[string]
RefGeneration(ref string) uint64
}
MetadataBackend is the blob/ref boundary used by metadata persistence. It contains no knowledge of branch or stack metadata schemas.
type MetadataCacheSummary ¶ added in v0.18.0
MetadataCacheSummary captures cumulative metadata-cache activity since process start. Used by tests and the metadata store.
type MetadataReadResults ¶ added in v0.28.0
type MetadataReadResults[T any] struct { ReadResults[T] Versions map[string]string }
MetadataReadResults keeps versions alongside values, including absent refs. A corrupt record still has a version, allowing a guarded deletion.
func (MetadataReadResults[T]) Record ¶ added in v0.28.0
func (r MetadataReadResults[T]) Record(name string) (MetadataRecord[T], error)
type MetadataRecord ¶ added in v0.28.0
MetadataRecord binds a value to the exact ref version read with it. An empty SHA denotes an observed absence, not permission for an unconditional write.
type MetadataStore ¶ added in v0.28.0
type MetadataStore struct {
// contains filtered or unexported fields
}
MetadataStore owns metadata serialization, caching, and persistence. Engines own a store independently of their Git runner.
func NewMetadataStore ¶ added in v0.28.0
func NewMetadataStore(backend MetadataBackend) *MetadataStore
func (*MetadataStore) ClearMetadataCache ¶ added in v0.28.0
func (r *MetadataStore) ClearMetadataCache()
ClearMetadataCache clears the in-memory metadata cache. This should be called before a full rebuild to ensure stale entries from external changes (e.g., branches created in another terminal) are not retained.
func (*MetadataStore) DeleteMetadata ¶ added in v0.28.0
func (r *MetadataStore) DeleteMetadata(ctx context.Context, branchName string) error
func (*MetadataStore) GetStackMetaRefSHA ¶ added in v0.28.0
func (r *MetadataStore) GetStackMetaRefSHA(ctx context.Context, stackID string) string
GetStackMetaRefSHA returns the current SHA of a stack metadata ref, or empty string if not found.
func (*MetadataStore) InvalidateMetadata ¶ added in v0.28.0
func (r *MetadataStore) InvalidateMetadata(branchNames ...string)
InvalidateMetadata drops the cached records and write expectations, shared and local, for the given branches. Callers use it after a ref write the store did not perform was rejected: the expectation that write carried is known-stale, and keeping it would make the next read answer from cache and fail the same way again.
func (*MetadataStore) ListMetadata ¶ added in v0.28.0
func (*MetadataStore) ListStackMetas ¶ added in v0.28.0
ListStackMetas returns a map of stack IDs to their ref SHAs.
func (*MetadataStore) MetadataCacheStats ¶ added in v0.28.0
func (r *MetadataStore) MetadataCacheStats() MetadataCacheSummary
MetadataCacheStats returns cumulative hit/miss counts for the metadata cache since process start. Counts are read with atomics and are safe to call concurrently. Reset via ResetMetadataCacheStats (test-only).
func (*MetadataStore) ReadLocalMetadata ¶ added in v0.28.0
func (r *MetadataStore) ReadLocalMetadata(ctx context.Context, branchNames ...string) MetadataReadResults[*LocalMeta]
ReadLocalMetadata reads one or many local metadata records together. Missing records return empty metadata; corrupt or unreadable records have per-name errors so callers can explicitly choose whether to tolerate them.
func (*MetadataStore) ReadMetadata ¶ added in v0.28.0
func (r *MetadataStore) ReadMetadata(ctx context.Context, branchNames ...string) MetadataReadResults[*Meta]
ReadMetadata reads one or many branch records through the shared object reader. Results contain successful metadata and per-branch errors. Branches that don't have metadata will have an empty Meta struct in the results map. Only actual errors (not missing metadata) will be included in the errors map.
func (*MetadataStore) ReadStackMeta ¶ added in v0.28.0
ReadStackMeta reads stack metadata for a given stack ID. Returns nil with no error if the stack doesn't exist.
func (*MetadataStore) RecordCommitted ¶ added in v0.28.0
func (r *MetadataStore) RecordCommitted(tier MetadataTier, records ...CommittedMetadata)
RecordCommitted adopts refs this process itself just wrote outside the store — a transaction commit, a batched flag write, a restack's atomic branch and metadata update — as the expectations for the next write. Without it the store's recorded SHA predates this process's own write, so a following direct write either failed spuriously ("another process changed it") or, under the generation safety net alone, had to fall back to an unconditional write that would silently discard a change another process made in between.
Call it only after the ref update succeeded. The generation is read now, after the write; if another in-process write slipped in first, the recorded SHA is simply wrong and the next write fails its compare-and-swap, which is safe. A deleted ref is recorded as known-absent so the next write requires it to still be missing.
func (*MetadataStore) RenameMetadata ¶ added in v0.28.0
func (r *MetadataStore) RenameMetadata(ctx context.Context, oldName, newName string) error
func (*MetadataStore) ResetMetadataCacheStats ¶ added in v0.28.0
func (r *MetadataStore) ResetMetadataCacheStats()
ResetMetadataCacheStats zeroes the metadata cache counters. Intended for tests that need to assert behavior of a single operation in isolation.
func (*MetadataStore) SetLogger ¶ added in v0.28.0
func (r *MetadataStore) SetLogger(logger DebugLogger)
func (*MetadataStore) WriteBlobs ¶ added in v0.28.0
WriteBlobs serializes shared, local, or stack records together in input order. It creates objects only; the transaction applies the ref updates atomically.
func (*MetadataStore) WriteLocalMetadata ¶ added in v0.28.0
func (*MetadataStore) WriteLocalMetadataBlobs ¶ added in v0.28.0
func (r *MetadataStore) WriteLocalMetadataBlobs(ctx context.Context, metas []*LocalMeta) ([]string, error)
WriteLocalMetadataBlobs is the LocalMeta counterpart to WriteMetadataBlobs.
func (*MetadataStore) WriteMetadata ¶ added in v0.28.0
func (*MetadataStore) WriteMetadataBlobs ¶ added in v0.28.0
WriteMetadataBlobs marshals each Meta to JSON and writes all the blobs in one `git hash-object` invocation via CreateBlobs. Returns SHAs in input order. Does NOT update any refs — callers (transaction commit, MarkBranchesForPRBodyUpdate) pair the SHAs with ref updates afterwards.
func (*MetadataStore) WriteStackMeta ¶ added in v0.28.0
WriteStackMeta writes stack metadata for a given stack ID.
func (*MetadataStore) WriteStackMetaBlob ¶ added in v0.28.0
WriteStackMetaBlob creates a blob containing the stack metadata JSON and returns its SHA. This does NOT update any refs - use this for batched/transactional writes.
type MetadataTier ¶ added in v0.28.0
type MetadataTier int
MetadataTier selects the shared or the local metadata namespace.
const ( MetadataTierLocal )
type ModifiedBy ¶
type ModifiedBy struct {
GitName string `json:"gitName"`
GitEmail string `json:"gitEmail"`
GitHubUsername *string `json:"githubUsername,omitempty"`
}
ModifiedBy represents information about who last modified the metadata
type ObjectOperations ¶
type ObjectOperations interface {
// CreateBlobs writes one or many blobs, returning SHAs in input order.
CreateBlobs(ctx context.Context, contents ...string) ([]string, error)
ReadObjects(ctx context.Context, refs ...string) (map[string]BatchObject, error)
}
ObjectOperations provides low-level Git object operations.
type PRNumber ¶ added in v0.29.0
type PRNumber int
PRNumber is a GitHub pull request number. It is a distinct type so PR numbers cannot be confused with other integers (stack numbers, comment IDs, counts) at call sites; it marshals to JSON exactly like a plain int.
type PRState ¶ added in v0.22.0
type PRState string
PRState is a GitHub pull-request state as reported by the API (GraphQL uppercase form). Empty means unknown.
type PatchApplyMode ¶ added in v0.29.0
type PatchApplyMode int
PatchApplyMode selects how ApplyPatch handles hunks that do not apply cleanly.
const ( // PatchApplyStrict fails on any hunk that does not apply cleanly. PatchApplyStrict PatchApplyMode = iota // PatchApplyThreeWay falls back to a three-way merge (--3way). PatchApplyThreeWay )
type PatchOperations ¶
type PatchOperations interface {
ApplyPatch(ctx context.Context, patchFile string, mode PatchApplyMode) error
// ApplyPatchToWorktree applies a patch (read from stdin) to the working
// tree only, never the index. It applies atomically or fails leaving the
// working tree untouched, so it can never write conflict markers.
ApplyPatchToWorktree(ctx context.Context, patch string) error
CheckCommutation(ctx context.Context, hunk Hunk, commitSHA, parentSHA string) (bool, error)
}
PatchOperations handles patch operations.
type PathOperations ¶
type PathOperations interface {
CheckoutPaths(ctx context.Context, branch string, paths []string) error
RemovePaths(ctx context.Context, paths []string) error
}
PathOperations handles file path operations.
type PrInfoPersistence ¶
type PrInfoPersistence struct {
Number *PRNumber `json:"number,omitempty"`
Base *string `json:"base,omitempty"`
BaseSHA *string `json:"baseSHA,omitempty"`
URL *string `json:"url,omitempty"`
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
State *PRState `json:"state,omitempty"`
IsDraft *bool `json:"isDraft,omitempty"`
LockReason *LockReason `json:"lockReason,omitempty"`
MergeBranch *string `json:"mergeBranch,omitempty"`
}
PrInfoPersistence represents PR information for persistence
type PullResult ¶
type PullResult int
PullResult represents the result of a pull operation
const ( // PullDone indicates the pull was successful PullDone PullResult = iota // PullUnneeded indicates no pull was needed PullUnneeded // PullConflict indicates a conflict occurred during pull PullConflict )
type PushLeaseMode ¶ added in v0.28.0
type PushLeaseMode uint8
PushLeaseMode selects how a branch is protected against remote changes.
const ( // PushLeaseExplicit checks ExpectedRemoteSHA, including an absent remote ref. PushLeaseExplicit PushLeaseMode = iota // PushLeaseTracking checks the local remote-tracking ref. PushLeaseTracking // PushLeaseNone uses Git's normal fast-forward checks. PushLeaseNone )
type PushOptions ¶
PushOptions applies to every branch in a push. Lease policies belong to PushSpec.
type PushResults ¶ added in v0.28.0
PushResults holds each requested branch's error, or nil on success.
func (PushResults) One ¶ added in v0.28.0
func (r PushResults) One() error
One extracts a one-branch result without performing I/O.
type PushSpec ¶ added in v0.19.1
type PushSpec struct {
BranchName string
LeaseMode PushLeaseMode
// ExpectedRemoteSHA is the SHA the remote ref is expected to be at, used for
// PushLeaseExplicit. An empty value means the branch is not expected to exist
// on the remote yet (a create); the lease then asserts the ref is absent.
ExpectedRemoteSHA string
}
PushSpec describes a branch and its lease policy for PushBranches.
type ReadResult ¶ added in v0.28.0
ReadResult represents one observed input, including successful empty values.
type ReadResults ¶ added in v0.28.0
type ReadResults[T any] struct { // contains filtered or unexported fields }
ReadResults has one authoritative entry per input. An absent entry means the input was not read, rather than an empty success. Its zero value is ready to use.
func (ReadResults[T]) All ¶ added in v0.28.0
func (r ReadResults[T]) All() iter.Seq2[string, ReadResult[T]]
All iterates the recorded outcomes without allocating separate value/error maps.
func (ReadResults[T]) Errs ¶ added in v0.28.0
func (r ReadResults[T]) Errs() []error
Errs returns failures in input-name order for callers reporting a summary.
func (*ReadResults[T]) Fail ¶ added in v0.28.0
func (r *ReadResults[T]) Fail(name string, err error)
Fail records a failed read, replacing any earlier value.
func (ReadResults[T]) Failures ¶ added in v0.28.0
func (r ReadResults[T]) Failures() map[string]error
Failures returns a copy of the per-input errors.
func (ReadResults[T]) Get ¶ added in v0.28.0
func (r ReadResults[T]) Get(name string) (T, error)
Get returns the result for a requested input, including its read error.
func (ReadResults[T]) One ¶ added in v0.28.0
func (r ReadResults[T]) One() (T, error)
One extracts a one-input read without repeating the input expression.
func (*ReadResults[T]) Record ¶ added in v0.28.0
func (r *ReadResults[T]) Record(name string, value T, err error)
Record replaces an input's outcome, so a failure cannot coexist with a success.
func (*ReadResults[T]) Set ¶ added in v0.28.0
func (r *ReadResults[T]) Set(name string, value T)
Set records a successful read, including a zero or nil value.
func (ReadResults[T]) Split ¶ added in v0.28.0
func (r ReadResults[T]) Split() (map[string]T, map[string]error)
Split returns independent maps for callers that process successes and failures separately.
func (ReadResults[T]) Values ¶ added in v0.28.0
func (r ReadResults[T]) Values() map[string]T
Values returns a copy of the successful results.
func (ReadResults[T]) ValuesAndErrors ¶ added in v0.28.0
func (r ReadResults[T]) ValuesAndErrors() (map[string]T, []error)
ValuesAndErrors returns values alongside a deterministic error summary.
type RebaseOperations ¶
type RebaseOperations interface {
Rebase(ctx context.Context, spec RebaseSpec) (RebaseOutcome, error)
RebaseContinue(ctx context.Context) (RebaseOutcome, error)
RebaseContinueNoEdit(ctx context.Context) (RebaseOutcome, error)
RebaseAbort(ctx context.Context) error
InteractiveRebase(ctx context.Context, onto string) error
IsRebaseInProgress(ctx context.Context) bool
GetRebaseHead(ctx context.Context) (string, error)
CheckRebaseInProgress(ctx context.Context) error
}
RebaseOperations handles rebase operations.
type RebaseOutcome ¶
type RebaseOutcome struct {
Result RebaseResult
RerereResolvedCount int
}
RebaseOutcome represents the result of a rebase operation, including any conflicts that git rerere resolved automatically.
func AutoContinueRerereRebase ¶
func AutoContinueRerereRebase(ctx context.Context, r Runner, originalErr error) (RebaseOutcome, []string, error)
AutoContinueRerereRebase drives `git rebase --continue` while rerere keeps all conflicts resolved (no unmerged files remain). It returns:
- RebaseOutcome with Result=RebaseDone and the count of rerere-resolved commits when the rebase completes.
- RebaseOutcome with Result=RebaseConflict and the list of unmerged files when rerere cannot resolve a conflict.
- a non-nil error if `rebase --continue` fails unexpectedly or the iteration cap is hit. The originalErr is wrapped into these errors so callers keep the context that triggered auto-continue.
type RebaseResult ¶
type RebaseResult int
RebaseResult represents the result of a rebase operation
const ( // RebaseDone indicates the rebase was successful RebaseDone RebaseResult = iota // RebaseConflict indicates a conflict occurred during rebase RebaseConflict )
type RebaseSpec ¶ added in v0.29.0
type RebaseSpec struct {
// Branch is the branch whose commits are replayed.
Branch string
// Onto is the new base the commits land on.
Onto string
// OldBase is the exclusive lower bound of the replayed range.
OldBase string
}
RebaseSpec names the three refs of a `git rebase --onto` invocation: the commits in OldBase..Branch are replayed onto Onto.
type RecentCommit ¶
type RecentCommit struct {
SHA string
Subject string
Author string
Date time.Time
PRNumber PRNumber // parsed from subject suffix "(#123)" if present
Kind RecentCommitKind // derived from trailer metadata
StackSize int // from Stackit-Stack-Size trailer (0 if absent)
StackPRNumbers []PRNumber // from Stackit-PRs trailer
StackScope string // from Stackit-Scope trailer (empty if absent)
}
RecentCommit represents a commit from the git log with optional stack trailer metadata.
func (RecentCommit) ConstituentPRTitles ¶ added in v0.22.0
func (c RecentCommit) ConstituentPRTitles(prTitles map[PRNumber]string) map[PRNumber]string
ConstituentPRTitles returns the subset of prTitles keyed by a stack-merge's constituent PR numbers, or nil when the commit is not a stack-merge or no titles apply.
func (RecentCommit) DisplayMessage ¶ added in v0.22.0
func (c RecentCommit) DisplayMessage(prTitles map[PRNumber]string) string
DisplayMessage returns the display message for a commit: a stack-merge uses its consolidation PR's title when available, replacing the raw "Merge pull request #N from ..." subject; everything else falls back to the commit subject.
type RecentCommitKind ¶
type RecentCommitKind string
RecentCommitKind describes the presentation type of a trunk commit.
const ( RecentCommitKindRegular RecentCommitKind = "regular" RecentCommitKindStackMerge RecentCommitKind = "stack-merge" )
type RecentCommits ¶ added in v0.22.0
type RecentCommits []RecentCommit
RecentCommits is an ordered collection of commits returned from git log.
func (RecentCommits) Collapse ¶ added in v0.22.0
func (commits RecentCommits) Collapse() RecentCommits
Collapse returns the commits with constituent-PR commits dropped when their PR number is already represented by a stack-merge consolidation commit in the same slice. Input order is preserved.
It is the dedup half shared by the HTTP "recently merged" mapper and the `stackit log` command, so both collapse consolidated stacks identically. Presentation shaping (terminal vs JSX) stays with each caller; the PR-title enrichment they both need lives in PRTitleNumbers / CollapsedMessage / ConstituentPRTitles below.
func (RecentCommits) PRTitleNumbers ¶ added in v0.22.0
func (commits RecentCommits) PRTitleNumbers() []PRNumber
PRTitleNumbers returns the unique PR numbers whose titles are needed to enrich the given commits: for each stack-merge, its consolidation PR plus its constituent PRs. Regular (non-stack) commits contribute nothing — their PR title is never displayed — so callers don't over-fetch. Order is first-seen stable. Safe to call on either the raw or the collapsed slice: collapse only drops covered regular commits, never stack-merges, so both yield the same set.
type RefDecoration ¶ added in v0.21.0
type RefDecoration struct {
Name string // short ref name, e.g. "main" or "v1.4.0"
IsTag bool // true for refs/tags/*, false for refs/heads/*
}
RefDecoration is a single local ref (branch head or tag) pointing at a commit. It backs git-log-style "(main, tag: v1.4.0)" annotations.
type RefOperations ¶
type RefOperations interface {
GetUntrackedFilesIn(ctx context.Context, worktreePath WorktreePath) ([]string, error)
TreeContainsAnyPath(ctx context.Context, rev string, paths []string) (collides, known bool)
UpdateRefs(ctx context.Context, updates []RefUpdate, reflogMessage string) error
DeleteRefs(ctx context.Context, refNames ...string) error
VerifyRef(ctx context.Context, refName string) error
RefGeneration(ref string) uint64
ListRefs(ctx context.Context, prefix string) (map[string]string, error)
// RefDecorations returns local branch and tag refs grouped by the commit SHA
// they point at, dereferencing annotated tags to the wrapped commit.
RefDecorations(ctx context.Context) (map[string][]RefDecoration, error)
}
RefOperations provides low-level reference operations.
type RefUpdate ¶
type RefUpdate struct {
RefName string
NewSHA string
OldSHA string // Optional: for optimistic locking verification
MustNotExist bool // Require the ref to be absent when creating it.
IsDelete bool // If true, this is a deletion instead of an update
}
RefUpdate represents a single reference update operation.
type RemoteBranchSHAs ¶ added in v0.29.0
RemoteBranchSHAs is remote branch name (without refs/heads/) -> tip SHA, as listed by `git ls-remote --heads`.
type RemoteOperations ¶
type RemoteOperations interface {
FetchRemoteShas(ctx context.Context, remote string) (RemoteBranchSHAs, error)
FindRemoteBranch(ctx context.Context, remote string) (string, error)
PushBranches(ctx context.Context, remote string, specs []PushSpec, opts PushOptions) PushResults
PullBranch(ctx context.Context, remote, branchName string) (PullResult, error)
UpdateBranchFromRemote(ctx context.Context, remote, branchName string) (PullResult, error)
FetchRefs(ctx context.Context, remote string, refspecs ...string) error
PushMetadataRefs(ctx context.Context, branches []string) error
FetchMetadataRefs(ctx context.Context) error
DeleteRemoteMetadataRefs(ctx context.Context, branches ...string) error
TestRemoteRefCompatibility(ctx context.Context) error
PushStackMetaRefs(ctx context.Context, stackIDs []string) error
FetchStackMetaRefs(ctx context.Context) error
DeleteRemoteStackMetaRefs(ctx context.Context, stackIDs []string) error
}
RemoteOperations handles interaction with remote repositories.
type RemoteRepository ¶ added in v0.25.0
RemoteRepository identifies the remote host and repository used for GitHub operations. The zero value represents a remote that cannot be mapped to a hosted owner/name repository, such as a local test remote.
func ParseRemoteRepository ¶ added in v0.25.0
func ParseRemoteRepository(remoteURL string) (RemoteRepository, error)
ParseRemoteRepository extracts host, owner, and repository name from common Git remote URL forms. Local paths are not an error; they return the zero value because callers may use them in tests or non-GitHub workflows.
func (RemoteRepository) IsHosted ¶ added in v0.25.0
func (r RemoteRepository) IsHosted() bool
IsHosted reports whether the remote identifies a hosted owner/name repository.
type RepositoryReader ¶
type RepositoryReader interface {
GetRemote(ctx context.Context) string
GetConfig(ctx context.Context, key string) (string, error)
GetConfigAll(key string) ([]string, error)
RepoRoot() string
DiscoverRepoRoot() (string, error)
// GetGitCommonDir returns the path to the shared .git directory.
// For regular repos this is the same as .git, but for worktrees it returns
// the main repository's .git directory (where config is stored).
GitCommonDir() (string, error)
IsInsideRepo() bool
GetUserName(ctx context.Context) (string, error)
GetRepoInfo(ctx context.Context) (RemoteRepository, error)
}
RepositoryReader provides read access to repository configuration and state.
type RepositoryWriter ¶
type RepositoryWriter interface {
InitDefaultRepo() error
SetConfig(key, value string) error
AddConfigValue(key, value string) error
EnsureMetadataRefspecConfigured(ctx context.Context) error
EnsureStackMetaRefspecConfigured(ctx context.Context) error
}
RepositoryWriter provides write access to repository configuration.
type ResetOperations ¶
type ResetOperations interface {
HardReset(ctx context.Context, revision string) error
ResetMerge(ctx context.Context, revision string) error
SoftReset(ctx context.Context, revision string) error
MixedReset(ctx context.Context, revision string) error
}
ResetOperations handles reset operations.
type RevRange ¶ added in v0.22.0
RevRange is a base..head revision range. Functions that walk or diff a range take it instead of two adjacent strings so the direction is explicit at every call site — transposed base/head reads wrong instead of silently reversing the diff.
type Runner ¶
type Runner interface {
// Repository access and configuration
RepositoryReader
RepositoryWriter
// Remote operations
RemoteOperations
// Branch operations
BranchReader
BranchWriter
// Commit and revision access
CommitReader
// Diff and comparison
DiffOperations
// Staging area
StagingOperations
// Commit creation
CommitWriter
// Advanced git operations
RebaseOperations
MergeOperations
CherryPickOperations
StashOperations
ResetOperations
PathOperations
PatchOperations
// Worktree management
WorktreeOperations
WorktreeRegistryOperations
// Repository status
StatusOperations
// Low-level operations
RefOperations
ObjectOperations
// Environment
GitVersion(ctx context.Context) (Version, error)
// Raw command execution
Run(ctx context.Context, args ...string) (string, error)
RunRaw(ctx context.Context, args ...string) (string, error)
RunWithEnv(ctx context.Context, env []string, args ...string) (string, error)
RunInteractive(ctx context.Context, args ...string) error
RunGH(ctx context.Context, args ...string) (string, error)
// Logging
SetLogger(logger DebugLogger)
}
Runner defines the interface for git operations used by the engine. This allows the engine to be used with both real git and mock implementations.
Runner is a composite interface that embeds smaller, focused interfaces for better modularity and testability. Each embedded interface represents a logical grouping of related git operations.
func NewRunner ¶
func NewRunner(logger DebugLogger) Runner
NewRunner returns a standard implementation of Runner that uses the current working directory as its repository root.
func NewRunnerWithPath ¶
func NewRunnerWithPath(repoRoot string, logger DebugLogger) Runner
NewRunnerWithPath returns a Runner that operates on a specific repo path. This is safe for parallel tests since it doesn't rely on global state.
type SquashMergeCache ¶ added in v0.21.0
type SquashMergeCache struct {
// contains filtered or unexported fields
}
SquashMergeCache memoizes immutable commit patch IDs for one higher-level operation. Create one at the operation boundary and pass it through repeated IsSquashMerged calls that scan the same target history.
func NewSquashMergeCache ¶ added in v0.21.0
func NewSquashMergeCache() *SquashMergeCache
NewSquashMergeCache creates an operation-scoped cache for repeated IsSquashMerged checks against overlapping target history.
type StackDescription ¶
type StackDescription struct {
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
}
StackDescription holds stack-level title and description. This is stored on the root branch of a stack.
func (*StackDescription) IsEmpty ¶
func (sd *StackDescription) IsEmpty() bool
IsEmpty returns true if both title and description are empty.
type StackMeta ¶
type StackMeta struct {
ID string `json:"id"` // Matches ref name (timestamp-sanitized-root)
Title string `json:"title,omitempty"` // Stack title
Description string `json:"description,omitempty"` // Stack description
CreatedAt time.Time `json:"createdAt"` // When stack was created
CreatedBy string `json:"createdBy,omitempty"` // Who created the stack (git user)
}
StackMeta represents stack-level metadata stored in Git refs. This is separate from branch metadata (Meta) and survives branch operations like merging the root branch.
func (*StackMeta) StackDescription ¶
func (sm *StackMeta) StackDescription() *StackDescription
StackDescription returns a StackDescription from the StackMeta fields. This provides compatibility with the existing StackDescription type.
type StagingOperations ¶
type StagingOperations interface {
StageAll(ctx context.Context) error
StagePatch(ctx context.Context) error
StageTracked(ctx context.Context) error
StageChanges(ctx context.Context, opts StagingOptions) error
HasStagedChanges(ctx context.Context) (bool, error)
HasUnstagedChanges(ctx context.Context) (bool, error)
HasUntrackedFiles(ctx context.Context) (bool, error)
GetUntrackedFiles(ctx context.Context) ([]string, error)
ParseStagedHunks(ctx context.Context) ([]Hunk, error)
StageHunks(ctx context.Context, hunks []Hunk) error
UnstageAll(ctx context.Context) error
}
StagingOperations handles staging area operations.
type StagingOptions ¶
StagingOptions defines which changes to stage
type StashApplyMode ¶ added in v0.28.0
type StashApplyMode int
StashApplyMode selects how a stash entry is put back onto the working tree.
const ( // StashApplyWithIndex restores the staged/unstaged split the stash was // created with. StashApplyWithIndex StashApplyMode = iota // StashApplyWorktreeOnly brings every change back as an unstaged // modification. StashApplyWorktreeOnly )
type StashCapture ¶ added in v0.28.0
StashCapture holds a stash and the index flags that a commit cannot encode.
type StashOperations ¶
type StashOperations interface {
StashPush(ctx context.Context, message string) (string, error)
StashPushStaged(ctx context.Context, message string) (string, error)
StashDrop(ctx context.Context, ref string) error
StashPop(ctx context.Context) error
StashPopRef(ctx context.Context, ref string) error
StashCreate(ctx context.Context, message string) (StashCapture, error)
RestoreIntentToAdd(ctx context.Context, paths []string) error
StashApplyRef(ctx context.Context, ref string, mode StashApplyMode) error
CaptureUntracked(ctx context.Context, message string) (string, error)
RestoreUntracked(ctx context.Context, commitSHA string) (int, error)
ListStash(ctx context.Context) (string, error)
}
StashOperations handles stash operations.
type StatusOperations ¶
type StatusOperations interface {
ReadWorktreeStatus(ctx context.Context) (WorktreeStatus, error)
GetStatusPorcelain(ctx context.Context) (string, error)
GetReflog(ctx context.Context, count int, format string) (string, error)
HasUncommittedChanges(ctx context.Context) bool
}
StatusOperations provides repository status information.
type Version ¶ added in v0.25.0
Version identifies a Git release by the components Stackit needs for feature gates. Patch versions do not affect any currently supported gate.
type Worktree ¶ added in v0.18.0
type Worktree struct {
Path WorktreePath
Branch string // empty when the worktree is at detached HEAD
}
Worktree represents a single entry from `git worktree list`.
type WorktreeCheckoutMode ¶ added in v0.29.0
type WorktreeCheckoutMode int
WorktreeCheckoutMode controls whether a new worktree populates its working directory (`git worktree add --no-checkout`).
const ( // WorktreeCheckoutFiles checks out the working tree files. WorktreeCheckoutFiles WorktreeCheckoutMode = iota // WorktreeNoCheckout creates the worktree without populating files. WorktreeNoCheckout )
type WorktreeDetachMode ¶ added in v0.21.0
type WorktreeDetachMode int
WorktreeDetachMode controls whether a new worktree checks out its branch normally or at a detached HEAD (`git worktree add --detach`).
const ( // WorktreeAttached checks out the branch normally (HEAD attached to it). WorktreeAttached WorktreeDetachMode = iota // WorktreeDetached adds the worktree at a detached HEAD. WorktreeDetached )
type WorktreeHeldError ¶ added in v0.25.0
type WorktreeHeldError struct {
Branch string
WorktreePath WorktreePath
Reason string
}
WorktreeHeldError reports a ref move declined because a worktree holding the branch would lose work.
This is a hold, not a failure. Callers whose remaining work does not depend on the ref move should report it and carry on rather than aborting: refusing to fast-forward trunk is no reason to skip branch cleanup and restack. See "Hold Trunk Never, Report Holds Always" in .claude/rules/worktree-safety.md.
func (*WorktreeHeldError) Error ¶ added in v0.25.0
func (e *WorktreeHeldError) Error() string
"move" covers both callers: a fast-forward and a reset both move the branch ref out from under whatever worktree has it checked out.
type WorktreeList ¶ added in v0.18.0
type WorktreeList []Worktree
WorktreeList is the parsed result of one `git worktree list --porcelain` invocation. Callers should pass it down per-batch instead of calling ListWorktrees per branch — see PathForBranch for the common lookup.
func (WorktreeList) IsMain ¶ added in v0.25.0
func (l WorktreeList) IsMain(path WorktreePath) bool
IsMain reports whether path is the repo's main working tree, which can never be removed with `git worktree remove`.
Prefer this over IsMainWorktree for removal guards. IsMainWorktree compares against whatever the caller believes the repo root to be, and an engine built inside a temporary worktree believes it is that worktree — so the main checkout does not match, the guard passes, and git is asked to remove the user's working tree.
Uncertainty resolves to true: with no list to compare against, or paths that cannot be resolved, the caller must not proceed to remove.
func (WorktreeList) MainPath ¶ added in v0.25.0
func (l WorktreeList) MainPath() WorktreePath
MainPath returns the main working tree's path. `git worktree list` always reports the main worktree first and linked worktrees after it, so the first entry is authoritative regardless of which worktree the command ran from.
func (WorktreeList) PathForBranch ¶ added in v0.18.0
func (l WorktreeList) PathForBranch(branchName string) WorktreePath
PathForBranch returns the worktree path where branchName is checked out, or "" if no worktree currently has it.
func (WorktreeList) Paths ¶ added in v0.18.0
func (l WorktreeList) Paths() []WorktreePath
Paths returns just the worktree paths.
type WorktreeMeta ¶
type WorktreeMeta struct {
Name WorktreeName `json:"name,omitempty"` // User-provided name for display (new worktrees only)
Path WorktreePath `json:"path"` // Absolute path to worktree
AnchorBranch string `json:"stackRoot"` // Anchor branch for worktree (JSON: stackRoot for backwards compat)
CreatedAt time.Time `json:"createdAt"` // When worktree was created
MainRepoDir string `json:"mainRepoDir"` // Path to main repo (for detection)
}
WorktreeMeta represents worktree tracking metadata stored in local Git refs
type WorktreeName ¶ added in v0.29.0
type WorktreeName string
WorktreeName identifies a Stackit-managed worktree's user-facing name.
func (WorktreeName) String ¶ added in v0.29.0
func (n WorktreeName) String() string
type WorktreeOperations ¶
type WorktreeOperations interface {
AddWorktree(ctx context.Context, path WorktreePath, branch string, detach WorktreeDetachMode) error
AddWorktreeWithOptions(ctx context.Context, path WorktreePath, branch string, detach WorktreeDetachMode, checkout WorktreeCheckoutMode) error
RemoveWorktree(ctx context.Context, path WorktreePath) error
ForceRemoveWorktree(ctx context.Context, path WorktreePath) error
ListWorktrees(ctx context.Context) (WorktreeList, error)
PruneWorktrees(ctx context.Context) error
GetWorktreePathForBranch(ctx context.Context, branchName string) (WorktreePath, error)
GetWorktreeCurrentBranch(ctx context.Context, worktreePath WorktreePath) (string, error)
ResetWorktreeWorkingDir(ctx context.Context, worktreePath WorktreePath) error
WorktreeHasUncommittedChanges(ctx context.Context, worktreePath WorktreePath) (bool, error)
WorktreeHasTrackedChanges(ctx context.Context, worktreePath WorktreePath) (bool, error)
// WorktreeResetBlocker reports why resetting worktreePath to incomingRev
// would destroy work, or "" when it is safe.
WorktreeResetBlocker(ctx context.Context, worktreePath WorktreePath, incomingRev string) string
// ListIgnoredFiles returns repository-relative paths that Git currently
// classifies as ignored in the requested worktree.
ListIgnoredFiles(ctx context.Context, worktreePath WorktreePath) ([]string, error)
}
WorktreeOperations handles worktree management.
type WorktreePath ¶ added in v0.29.0
type WorktreePath string
WorktreePath is the root directory of a physical Git checkout: the main working tree or a linked worktree. Keeping it distinct from plain strings stops a worktree location from being confused with a branch name, a repository-relative file path, or an arbitrary directory at call sites.
func CanonicalWorktreePath ¶ added in v0.25.0
func CanonicalWorktreePath(path WorktreePath) (WorktreePath, error)
CanonicalWorktreePath returns an absolute path with every existing path component resolved. It deliberately resolves the deepest existing ancestor instead of requiring the final worktree directory to exist: registration happens after creation but unregistering often happens after removal. Using the same canonical spelling in both cases keeps the reverse registration ref addressable through symlinked bases such as /tmp on macOS.
func (WorktreePath) String ¶ added in v0.29.0
func (p WorktreePath) String() string
type WorktreeRegistration ¶ added in v0.28.0
type WorktreeRegistration struct {
Meta *WorktreeMeta
Err error
}
WorktreeRegistration is one entry under WorktreeRefPrefix. Err is set when the entry cannot be read or parsed; Meta is nil then.
type WorktreeRegistryOperations ¶
type WorktreeRegistryOperations interface {
ReadWorktreeMeta(ctx context.Context, stackRoot string) (*WorktreeMeta, error)
WriteWorktreeMeta(ctx context.Context, stackRoot string, meta *WorktreeMeta) error
DeleteWorktreeMeta(ctx context.Context, stackRoot string) error
ListWorktreeMetas(ctx context.Context) (map[string]*WorktreeMeta, error)
ListWorktreeRegistrations(ctx context.Context) (map[string]WorktreeRegistration, error)
}
WorktreeRegistryOperations handles stackit-managed worktree tracking (local-only refs).
type WorktreeStatus ¶ added in v0.28.0
WorktreeStatus is a point-in-time snapshot. Read it again after staging, committing, stashing, or any other index/worktree mutation.
func (WorktreeStatus) Clean ¶ added in v0.28.0
func (s WorktreeStatus) Clean() bool
Clean reports whether the index and worktree have no pending changes.
func (WorktreeStatus) HasUnstagedChanges ¶ added in v0.28.0
func (s WorktreeStatus) HasUnstagedChanges() bool
HasUnstagedChanges includes untracked files as well as tracked modifications.
Source Files
¶
- absorb.go
- branch_ops.go
- branches.go
- cherry_pick.go
- commit.go
- commit_info.go
- commit_metadata.go
- commit_range.go
- commit_ranges.go
- commit_reads.go
- commits.go
- config.go
- diff.go
- diff_reads.go
- doc.go
- errors.go
- exec.go
- gitdir.go
- hunk_split.go
- hunks.go
- interfaces.go
- merge_base.go
- merge_detection.go
- meta_accessors.go
- metadata.go
- metadata_cache.go
- metadata_store.go
- object_reader.go
- pull.go
- push.go
- read_results.go
- rebase.go
- recent_commits.go
- ref_decorations.go
- remote.go
- remote_timeout.go
- repo.go
- reset.go
- revision_format.go
- runner.go
- stack_metadata.go
- staging.go
- stash.go
- trunk_collapse.go
- version.go
- worktree.go
- worktree_capture.go
- worktree_status.go
- write_results.go