Documentation
¶
Index ¶
- Variables
- func HasLegacyState(commonDir string) (bool, error)
- func MigrateLegacyState(commonDir string) error
- func NearestSurvivingBranch(order []string, target string, survives func(string) bool) string
- func ReadStateFile(path string) ([]byte, error)
- func Save(gitDir string, sf *StackFile) error
- func SaveNonBlocking(gitDir string, sf *StackFile)
- func SaveWithLock(gitDir string, sf *StackFile, lock *FileLock) error
- func WriteAtomic(path string, data []byte) error
- type BranchRef
- type FileLock
- type LockError
- type MigrationBlockedError
- type MigrationConflictError
- type PullRequestRef
- type Stack
- func (s *Stack) ActiveBaseBranch(branch string) string
- func (s *Stack) ActiveBranchIndices() []int
- func (s *Stack) ActiveBranches() []BranchRef
- func (s *Stack) BaseBranch(branch string) string
- func (s *Stack) BranchNames() []string
- func (s *Stack) Contains(branch string) bool
- func (s *Stack) DisplayChain() string
- func (s *Stack) FirstActiveBranchIndex() int
- func (s *Stack) IndexOf(branch string) int
- func (s *Stack) IsFullyMerged() bool
- func (s *Stack) MergedBranches() []BranchRef
- func (s *Stack) QueuedBranches() []BranchRef
- type StackFile
- func (sf *StackFile) AddStack(s Stack)
- func (sf *StackFile) FindAllStacksForBranch(branch string) []*Stack
- func (sf *StackFile) FindStackByPRNumber(prNumber int) (*Stack, *BranchRef)
- func (sf *StackFile) IndexOfStack(s *Stack) int
- func (sf *StackFile) RemoveStack(idx int)
- func (sf *StackFile) RemoveStackForBranch(branch string) bool
- func (sf *StackFile) ValidateNoDuplicateBranch(branch string) error
- type StaleError
Constants ¶
This section is empty.
Variables ¶
var LockTimeout = 5 * time.Second
LockTimeout is how long Lock and LockOperation wait for an exclusive lock.
Functions ¶
func HasLegacyState ¶ added in v0.2.0
HasLegacyState reports linked-worktree catalogs or an unfinished migration. It inspects every retained administration directory, regardless of whether its worktree still exists. It never invokes Git or changes worktree state.
func MigrateLegacyState ¶ added in v0.2.0
MigrateLegacyState consolidates legacy catalogs into the common directory. The caller must hold LockOperation; this function takes the catalog lock. Only disjoint stacks and equivalent duplicates are merged. Original bytes are retained in *.pre-worktree-migration backups after common publication. Old and new gh-stack versions must not write catalogs concurrently.
func NearestSurvivingBranch ¶ added in v0.0.8
NearestSurvivingBranch returns the branch nearest to target within the ordered branch-name list `order` for which `survives` reports true, preferring the neighbor above (later in the slice, away from the trunk) and then the neighbor below (earlier in the slice, toward the trunk).
It returns "" when target is not present in order, or when no other branch in order survives. Callers layer their own fallback and any name translation around this search. It is shared by the checkout-branch selection in `gh stack modify` and `gh stack sync`.
func ReadStateFile ¶ added in v0.2.0
ReadStateFile reads a complete state file, allowing WriteAtomic to replace it while the read is in progress. On Windows, its handle permits delete sharing.
func Save ¶
Save acquires an exclusive lock on the stack file, verifies the file hasn't been modified since Load (optimistic concurrency), writes sf as JSON, and releases the lock. The lock is held only for the read-compare-write window. Mutation callers must separately hold the operation lock across their Load/preflight/Save sequence; read-only refreshes should use SaveNonBlocking. Returns *LockError if the lock times out, or *StaleError if another process modified the file since it was loaded.
func SaveNonBlocking ¶
SaveNonBlocking attempts a best-effort metadata refresh without waiting for either the operation or catalog lock. Contention, stale data and I/O errors skip the refresh. Use Save for critical writes, including callers already holding the operation lock.
func SaveWithLock ¶ added in v0.0.3
SaveWithLock writes the stack file while the caller already holds the catalog lock (not merely the operation lock). The caller is responsible for acquiring and releasing the lock. Panics if lock is nil to catch programming errors.
func WriteAtomic ¶ added in v0.2.0
WriteAtomic publishes data at path using a fully written temporary file in the same directory. It preserves an existing regular file's permissions and uses 0644 for a new file. The parent directory must already exist. It does not acquire locks; callers must serialize mutations.
Types ¶
type BranchRef ¶
type BranchRef struct {
Branch string `json:"branch"`
Head string `json:"head,omitempty"`
Base string `json:"base,omitempty"`
PullRequest *PullRequestRef `json:"pullRequest,omitempty"`
// Queued is a transient (not persisted) flag indicating the branch's
// PR is currently in a merge queue. It is populated by syncStackPRs
// from the GitHub API on each command run.
Queued bool `json:"-"`
}
BranchRef represents a branch and its associated commit hash. For the trunk, Head stores the HEAD commit SHA. For stacked branches, Base stores the parent branch's HEAD SHA at the time of last sync/rebase, used to identify unique commits.
type FileLock ¶
type FileLock struct {
// contains filtered or unexported fields
}
FileLock provides an exclusive advisory catalog or operation lock.
func Lock ¶
Lock acquires an exclusive lock on the stack file in the given git directory. It retries with a non-blocking attempt every 100ms for up to LockTimeout.
Most callers should not use Lock directly — stack.Save() acquires the lock automatically. Use Lock only when you need to hold the lock across multiple operations (e.g. Load-Modify-SaveWithLock as an atomic unit).
func LockOperation ¶ added in v0.2.0
LockOperation serializes mutations in a repository's resolved common directory. Acquire it before loading mutation state or taking the catalog lock. Save only takes the catalog lock, so it may be used while this is held.
func TryLockOperation ¶ added in v0.2.0
TryLockOperation attempts to acquire the operation lock without waiting. A false result with no error means contention; other failures are returned.
func (*FileLock) Unlock ¶
func (l *FileLock) Unlock()
Unlock releases the lock. The lock file is intentionally left on disk to avoid a race where another process opens the same path, blocks on flock, then wakes up holding a lock on an unlinked inode while a third process creates a new file and locks a different inode.
type LockError ¶
type LockError struct {
Err error
}
LockError is returned when the catalog or operation lock times out. Callers can check for this with errors.As to distinguish lock failures from other errors.
type MigrationBlockedError ¶ added in v0.2.0
type MigrationBlockedError struct {
RecoveryPaths []string
}
MigrationBlockedError identifies legacy recovery records whose original catalogs must remain available to the operation's original worktree.
func (*MigrationBlockedError) Error ¶ added in v0.2.0
func (e *MigrationBlockedError) Error() string
type MigrationConflictError ¶ added in v0.2.0
MigrationConflictError reports catalog definitions or migration artifacts that cannot be reconciled without choosing which tracking state to keep.
func (*MigrationConflictError) Error ¶ added in v0.2.0
func (e *MigrationConflictError) Error() string
type PullRequestRef ¶
type PullRequestRef struct {
Number int `json:"number"`
ID string `json:"id,omitempty"`
URL string `json:"url,omitempty"`
Merged bool `json:"merged,omitempty"`
MergedHead string `json:"mergedHead,omitempty"`
}
PullRequestRef holds relatively immutable metadata about an associated PR.
type Stack ¶
type Stack struct {
ID string `json:"id,omitempty"`
Number int `json:"number,omitempty"`
Trunk BranchRef `json:"trunk"`
Branches []BranchRef `json:"branches"`
}
Stack represents a single stack of branches.
func (*Stack) ActiveBaseBranch ¶
ActiveBaseBranch returns the effective parent for a branch, skipping merged and queued ancestors. For the first active branch (or any branch whose downstack is all merged/queued), this returns the trunk.
func (*Stack) ActiveBranchIndices ¶
ActiveBranchIndices returns the indices of all active (not merged, not queued) branches.
func (*Stack) ActiveBranches ¶
ActiveBranches returns only branches that are pushable (not merged, not queued).
func (*Stack) BaseBranch ¶
BaseBranch returns the base branch for the given branch in the stack. For the first branch, this is the trunk. For others, it's the previous branch.
func (*Stack) BranchNames ¶
BranchNames returns the list of branch names in order.
func (*Stack) Contains ¶
Contains returns true if the branch is part of this stack (including trunk).
func (*Stack) DisplayChain ¶
DisplayChain returns a human-readable chain representation of the stack. Format: (trunk) <- branch1 <- branch2 <- branch3
func (*Stack) FirstActiveBranchIndex ¶
FirstActiveBranchIndex returns the index of the first active (not merged, not queued) branch, or -1.
func (*Stack) IndexOf ¶
IndexOf returns the index of the given branch in the stack, or -1 if not found.
func (*Stack) IsFullyMerged ¶
IsFullyMerged returns true if all branches in the stack have been merged.
func (*Stack) MergedBranches ¶
MergedBranches returns only merged branches, preserving order.
func (*Stack) QueuedBranches ¶
QueuedBranches returns only queued branches, preserving order.
type StackFile ¶
type StackFile struct {
SchemaVersion int `json:"schemaVersion"`
Repository string `json:"repository"`
Stacks []Stack `json:"stacks"`
// contains filtered or unexported fields
}
StackFile represents the JSON catalog stored in Git's common directory.
func Load ¶
Load reads the catalog from the given directory, normally Git's common directory. Legacy recovery may explicitly use a worktree's original directory. Returns an empty StackFile if the file does not exist. The returned StackFile records a checksum of the on-disk content so that Save can detect concurrent modifications.
func (*StackFile) FindAllStacksForBranch ¶
FindAllStacksForBranch returns all stacks that contain the given branch.
func (*StackFile) FindStackByPRNumber ¶
FindStackByPRNumber returns the first stack and branch whose PR number matches. Returns nil, nil if no match is found.
func (*StackFile) IndexOfStack ¶ added in v0.0.7
IndexOfStack returns the index of the given stack within the file by identity (pointer), or -1 if it is not part of this file. Use it to locate a stack obtained from FindAllStacksForBranch before mutating the Stacks slice.
func (*StackFile) RemoveStack ¶
RemoveStack removes the stack at the given index.
func (*StackFile) RemoveStackForBranch ¶
RemoveStackForBranch removes the stack containing the given branch.
func (*StackFile) ValidateNoDuplicateBranch ¶
ValidateNoDuplicateBranch checks that the branch is not already in any stack.
type StaleError ¶
type StaleError struct {
Err error
}
StaleError is returned when the stack file was modified on disk since it was loaded. This indicates another process wrote to the file concurrently. Callers can check for this with errors.As.
func (*StaleError) Error ¶
func (e *StaleError) Error() string
func (*StaleError) Unwrap ¶
func (e *StaleError) Unwrap() error