Help us shape the future of Go! Take the 2026 Go Developer Survey

actions

package
v0.30.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package actions holds the reusable operations behind stackit's commands (create, submit, sync, ...), orchestrating the engine, git and GitHub layers. Interaction goes through prompt and handler interfaces that the CLI and TUI adapters implement.

Operations still being migrated take *app.Context; converted ones live in subpackages and take a context.Context plus a Deps struct of narrow interfaces (see docs/architecture.md).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContinueAction

func ContinueAction(ctx context.Context, deps ContinueDeps, opts ContinueOptions) error

ContinueAction performs the continue operation

func EnsureCanModify added in v0.30.1

func EnsureCanModify(ctx context.Context, eng OwnershipEngine, here Here, branches ...engine.Branch) error

EnsureCanModify refuses to mutate a stack from anywhere other than its managed worktree. The ownership relation is derived from the branch's stack root, while the invocation location comes from here.

Branch-level mutation checks deliberately do not live in engine.Branch: Branch has no command context, and the same branch can be valid in one worktree and invalid in another.

func EnsureCanModifyNames added in v0.30.1

func EnsureCanModifyNames(ctx context.Context, eng OwnershipEngine, here Here, branchNames ...string) error

EnsureCanModifyNames is EnsureCanModify for branch names.

func ManagedWorktreeHoldReason added in v0.30.1

func ManagedWorktreeHoldReason(ctx context.Context, eng ManagedWorktreeInspector, path engine.WorktreePath) string

ManagedWorktreeHoldReason returns why a managed worktree's stack must be left alone this pass, or "" when it is safe to touch.

A failed inspection counts as unsafe. The probe fails when git cannot read the worktree — an index.lock held by another process, unreadable permissions — and reading that as clean would move refs under a checkout whose contents are unknown, which is exactly what the hold exists to prevent.

A missing directory is the one exception: there is no working tree left to protect, and holding it would block sync's orphan cleanup, which exists to retire its registration.

func NewRestackRunner added in v0.30.1

func NewRestackRunner(deps RestackDeps) restack.Runner

NewRestackRunner builds the restack runner for deps, printing per-branch results as plain text.

func NewSnapshot

func NewSnapshot(command string, options ...SnapshotOption) engine.SnapshotOptions

NewSnapshot creates a new SnapshotOptions with the given command and options

func PRNumberForBranch added in v0.25.0

func PRNumberForBranch(eng engine.BranchReader, branchName string) *git.PRNumber

PRNumberForBranch returns the submitted PR number for a branch, when one is available in local metadata. Read failures are intentionally treated as an unknown number because progress reporting must not fail an operation.

func PluralIt

func PluralIt(plural bool) string

PluralIt returns "them" if plural is true, otherwise "it"

func PluralSuffix

func PluralSuffix(word string, plural bool) string

PluralSuffix returns the appropriate plural suffix for the given word if plural is true, otherwise empty string

func Pluralize

func Pluralize(word string, count int) string

Pluralize returns the plural form of word if count != 1, otherwise returns the singular form

func PushMetadataOnly

func PushMetadataOnly(ctx context.Context, out DebugLogger, eng MetadataPushEngine, branchNames []string) error

PushMetadataOnly pushes metadata refs without updating GitHub PRs. Use this when you want to push metadata changes but defer PR updates to sync.

func ResolveBranchName

func ResolveBranchName(ctx context.Context, eng CurrentBranchReader, branchName string) (string, error)

ResolveBranchName resolves a branch name, defaulting to current branch if empty. Returns errors.ErrNotOnBranchNoBranchSpecified if no branch specified and not on a branch.

func RestackAction

func RestackAction(ctx context.Context, deps RestackDeps, plan *RestackPlan, handler RestackHandler) error

RestackAction performs the restack operation using a pre-computed plan. Build the plan via PlanRestack — callers are expected to use the plan to gate UX decisions (e.g. whether to start a TUI), so requiring it here keeps the two phases consistent.

func WarnIfNonLinearRestore added in v0.30.1

func WarnIfNonLinearRestore(ctx context.Context, eng TopologyEngine, out Warner, linearStacks bool, operation string)

WarnIfNonLinearRestore reports when snapshot restoration brings back a topology that linear mode would not allow newly-created operations to make. linearStacks reflects stack.shape=linear.

Types

type BranchDeletionPlan

type BranchDeletionPlan struct {
	// BranchesToDelete maps branch name to deletion reason
	BranchesToDelete map[string]string
	// BranchesWithNewParents lists branches that will be reparented
	BranchesWithNewParents []string
	// SkippedInWorktree lists branches skipped due to being in a worktree
	SkippedInWorktree []string
	// UtilityBranches tracks which branches in BranchesToDelete are utility branches
	// (e.g., consolidated merge branches). These can be auto-confirmed for deletion
	// when their associated PR is closed/merged.
	UtilityBranches map[string]bool
	// UnpushedBranches tracks which branches in BranchesToDelete have unpushed local changes
	// (local branch is ahead of or diverged from remote)
	UnpushedBranches map[string]bool
	// contains filtered or unexported fields
}

BranchDeletionPlan contains the planned branch deletions before execution

func PlanBranchDeletions

func PlanBranchDeletions(ctx context.Context, deps CleanBranchesDeps, opts CleanBranchesOptions) (*BranchDeletionPlan, error)

PlanBranchDeletions identifies branches that should be deleted and builds a deletion plan. This does NOT execute any deletions - use ExecuteBranchDeletions to apply the plan.

type BranchDiffStats added in v0.23.0

type BranchDiffStats struct {
	FilesChanged int
	Additions    int
	Deletions    int
}

BranchDiffStats represents summary diff information for a branch. It is pure data; the JSON shape lives in the CLI adapter that renders it.

type BranchInfoPR added in v0.23.0

type BranchInfoPR struct {
	Number  *git.PRNumber
	Title   string
	State   git.PRState
	IsDraft bool
	URL     string
	Body    string
}

BranchInfoPR represents pull request information for a branch.

type BranchInfoQueryOptions added in v0.23.0

type BranchInfoQueryOptions struct {
	BranchName string
	Diff       bool
	Patch      bool
	Stat       bool
}

BranchInfoQueryOptions contains options for querying single-branch info.

type BranchInfoResult added in v0.23.0

type BranchInfoResult struct {
	Name         string
	IsCurrent    bool
	IsTrunk      bool
	IsLocked     bool
	IsFrozen     bool
	NeedsRestack bool
	Scope        string
	CommitDate   string
	Parent       string
	Children     []string
	// Trunk is the repository's trunk branch name, so renderers can style a
	// trunk parent or child without re-resolving it from the engine.
	Trunk            string
	PR               *BranchInfoPR
	CommitMessages   []string
	DiffStats        BranchDiffStats
	StackTitle       string
	StackDescription string
	PatchOutput      string
	DiffOutput       string
}

BranchInfoResult contains structured data for `stackit info` on a single branch.

func QueryBranchInfo added in v0.23.0

func QueryBranchInfo(ctx context.Context, eng engine.Engine, opts BranchInfoQueryOptions, debug branchInfoDebugLogger) (BranchInfoResult, error)

QueryBranchInfo gathers structured information for `stackit info`.

type CleanBranchesDeps added in v0.30.1

type CleanBranchesDeps struct {
	Engine engine.Engine
	Out    output.Output
	Log    output.Logger
}

CleanBranchesDeps are the collaborators branch cleanup needs.

type CleanBranchesOptions

type CleanBranchesOptions struct {
	Force             bool
	InManagedWorktree bool   // True if running from a stackit-managed worktree
	CurrentBranch     string // Name of the current branch (used to skip deletion in worktree)
	RemoteStatuses    engine.BranchRemoteStatuses
}

CleanBranchesOptions contains options for cleaning branches

type CleanBranchesResult

type CleanBranchesResult struct {
	DeletedBranches        map[string]string // name -> reason
	BranchesWithNewParents []string
	SkippedInWorktree      []string // branches that couldn't be deleted from worktree
	SkippedUnpushed        []string // branches skipped due to unpushed local changes
	SkippedCheckedOut      []string // branches checked out in the main working tree, which cannot be removed
}

CleanBranchesResult contains the result of cleaning branches

func ExecuteBranchDeletions

func ExecuteBranchDeletions(ctx context.Context, deps CleanBranchesDeps, plannedDeletion *BranchDeletionPlan, branchesToDelete map[string]bool) (*CleanBranchesResult, error)

ExecuteBranchDeletions executes a previously planned deletion. The branchesToDelete parameter allows filtering which branches from the plan to actually delete. If nil, all planned branches are deleted.

type ContinueDeps added in v0.30.1

type ContinueDeps struct {
	Engine   ContinueEngine
	Out      output.Output
	RepoRoot string
	// Restack resumes the branches the interrupted command still had queued.
	Restack restack.Runner
	// Conflicts prints the conflict status when the rebase stops again.
	Conflicts *restack.ConflictReporter
}

ContinueDeps are the collaborators continue needs.

type ContinueEngine added in v0.30.1

type ContinueEngine interface {
	engine.BranchLookup
	IsRebaseInProgress(ctx context.Context) bool
	CurrentBranch(ctx context.Context) *engine.Branch
	Trunk() engine.Branch
	StageAll(ctx context.Context) error
	ContinueRebase(ctx context.Context, spec engine.ContinueRebaseSpec) (engine.ContinueRebaseResult, error)
	CheckoutBranch(ctx context.Context, branch engine.Branch) error
	ListWorktrees(ctx context.Context) (git.WorktreeList, error)
}

ContinueEngine lists exactly the engine methods continue calls.

type ContinueOptions

type ContinueOptions struct {
	AddAll bool
}

ContinueOptions contains options for the continue command

type CurrentBranchReader added in v0.25.0

type CurrentBranchReader interface {
	CurrentBranch(ctx context.Context) *engine.Branch
}

CurrentBranchReader is the minimal dependency needed to resolve an omitted branch argument.

type DebugLogger added in v0.30.1

type DebugLogger interface {
	Debug(format string, args ...any)
}

DebugLogger receives diagnostics for best-effort steps that do not fail the operation. output.Output satisfies it.

type Here added in v0.30.1

type Here struct {
	InManagedWorktree bool
	// Worktree describes the managed worktree when InManagedWorktree is set.
	Worktree *engine.WorktreeInfo
}

Here is where a command runs: the main repository, or a stackit-managed worktree.

type ManagedWorktreeInspector added in v0.30.1

type ManagedWorktreeInspector interface {
	WorktreeRebaseInProgress(ctx context.Context, worktreePath engine.WorktreePath) bool
	WorktreeHasUncommittedChanges(ctx context.Context, worktreePath engine.WorktreePath) (bool, error)
}

ManagedWorktreeInspector is the narrow dependency ManagedWorktreeHoldReason needs.

type ManagedWorktreeSource added in v0.30.1

type ManagedWorktreeSource interface {
	ManagedWorktreeInspector
	ListManagedWorktrees(ctx context.Context) ([]engine.WorktreeInfo, error)
}

ManagedWorktreeSource is the engine surface ManagedWorktreeHolds needs.

type MetadataPushEngine

type MetadataPushEngine interface {
	BatchSetLastModifiedBy(ctx context.Context, branchNames []string) error
	PrepareRemoteMetadataPush(ctx context.Context) error
	PushMetadataForBranches(ctx context.Context, branchNames []string) error
}

MetadataPushEngine defines the engine capabilities needed for pushing metadata.

type MutationDeps added in v0.30.1

type MutationDeps struct {
	Out       output.Output
	Here      Here
	Snapshots Snapshots
	Restack   restack.Runner
}

MutationDeps are the collaborators every branch-rewriting action shares. Embed it in an action's Deps next to the action's own Engine interface.

type NullRestackHandler added in v0.30.1

type NullRestackHandler struct{}

NullRestackHandler is a no-op handler for testing or when output is not needed

func (*NullRestackHandler) OnRestackBranch added in v0.30.1

func (h *NullRestackHandler) OnRestackBranch(RestackBranchEvent)

OnRestackBranch implements RestackHandler.

func (*NullRestackHandler) OnRestackComplete added in v0.30.1

func (h *NullRestackHandler) OnRestackComplete(RestackSummary)

OnRestackComplete implements RestackHandler.

func (*NullRestackHandler) OnRestackStart added in v0.30.1

func (h *NullRestackHandler) OnRestackStart(_ int)

OnRestackStart implements RestackHandler.

type OwnershipEngine added in v0.30.1

type OwnershipEngine interface {
	engine.BranchLookup
	WorktreeOwnershipByStackRoot(ctx context.Context) (map[string]engine.WorktreeOwnership, error)
	GetStackRootForBranch(branch engine.Branch) string
}

OwnershipEngine is the engine surface the ownership guard reads.

type PRSync added in v0.30.1

type PRSync struct {
	Engine PRSyncEngine
	// GitHub returns the client, or nil when GitHub is unavailable. It is a
	// function so the client is only built when a PR is actually touched.
	GitHub   func() github.Client
	GHRunner github.GitCommandRunner
	Nav      pr.NavigationOptions
	Log      DebugLogger
}

PRSync pushes branch metadata and refreshes the matching PRs on GitHub: titles (scope prefix), body footers, and navigation comments.

func (PRSync) FetchContent added in v0.30.1

func (s PRSync) FetchContent(ctx context.Context, branches []string) map[git.PRNumber]github.PRContent

FetchContent fetches the current title and body for the PRs of the given branches in a single GraphQL query, keyed by PR number. Branches without a known PR number are skipped. On failure it returns an empty map; the per-branch update then falls back to a direct GetPullRequest.

func (PRSync) PushAndSync added in v0.30.1

func (s PRSync) PushAndSync(ctx context.Context, branchNames []string) error

PushAndSync pushes metadata for the given branches to remote and updates their PRs on GitHub

func (PRSync) UpdateBranch added in v0.30.1

func (s PRSync) UpdateBranch(ctx context.Context, name string, current map[git.PRNumber]github.PRContent)

UpdateBranch updates PR title and body footer for a single branch, using PR content pre-fetched in bulk by FetchContent. If the branch's PR is not present in current (a batch miss or fetch failure), it falls back to a direct GetPullRequest so the freshness guarantee is preserved.

func (PRSync) UpdateStack added in v0.30.1

func (s PRSync) UpdateStack(ctx context.Context, branches []string)

UpdateStack updates PR titles and body footers for a list of branches

type PRSyncEngine added in v0.30.1

type PRSyncEngine interface {
	engine.BranchReader
	MetadataPushEngine
	UpsertPrInfo(ctx context.Context, branch engine.Branch, prInfo *engine.PrInfo) error
	ClearNeedsPRBodyUpdate(ctx context.Context, branchName string) error
	GetNavigationCommentID(branch engine.Branch) (int64, error)
	SetNavigationCommentID(ctx context.Context, branch engine.Branch, commentID int64) error
	ClearNavigationCommentID(ctx context.Context, branch engine.Branch) error
}

PRSyncEngine lists the engine methods PRSync calls. pr.ComposeBody and pr.CreateNavigationComment read the stack through engine.BranchReader.

type RecoveryEngine added in v0.29.0

type RecoveryEngine interface {
	IsRebaseInProgress(ctx context.Context) bool
	IsMergeInProgress(ctx context.Context) bool
	RebaseAbort(ctx context.Context) error
	MergeAbort(ctx context.Context) error
	RestoreSnapshot(ctx context.Context, snapshotID string) error
	RestoreWorktree(ctx context.Context, snapshotID string) (bool, error)
}

RecoveryEngine is the engine surface shared by the commands that unwind a halted operation (abort, undo): abandoning Git's in-progress rebase or merge and rolling refs and the working tree back to a snapshot. Each command embeds it in its own consumer-side interface alongside the few extra methods it needs.

type RestackBranchEvent added in v0.30.1

type RestackBranchEvent struct {
	Branch              string
	Result              RestackResult
	NewRevision         string
	PRNumber            *git.PRNumber
	LockReason          engine.LockReason
	Frozen              bool
	HeldBy              string // why a worktree held this branch back (empty if it was not held)
	IsCurrent           bool
	Parent              string
	Reparented          bool
	OldParent           string
	NewParent           string
	RerereResolvedCount int
	StackRoot           string
}

RestackBranchEvent describes the outcome of restacking one branch. Keeping these facts together makes the shared presentation contract safe to extend without relying on positional arguments.

func (RestackBranchEvent) IsPlainUpToDate added in v0.30.1

func (e RestackBranchEvent) IsPlainUpToDate() bool

IsPlainUpToDate reports whether the event is a no-op with nothing worth showing: the branch was already current, and not locked, frozen, held back by a worktree, or reparented. A held branch reports the same RestackUnneeded status as one that needed no work, so it must be excluded here or "I protected your work" is silently counted as "already current".

type RestackBranchFunc added in v0.30.1

type RestackBranchFunc func(RestackBranchEvent)

RestackBranchFunc adapts a function to RestackHandler for callers that bracket the restack in a phase of their own (sync, submit) and only want the per-branch events.

func (RestackBranchFunc) OnRestackBranch added in v0.30.1

func (f RestackBranchFunc) OnRestackBranch(event RestackBranchEvent)

OnRestackBranch implements RestackHandler.

func (RestackBranchFunc) OnRestackComplete added in v0.30.1

func (f RestackBranchFunc) OnRestackComplete(RestackSummary)

OnRestackComplete implements RestackHandler.

func (RestackBranchFunc) OnRestackStart added in v0.30.1

func (f RestackBranchFunc) OnRestackStart(int)

OnRestackStart implements RestackHandler.

type RestackConflictPolicy added in v0.30.1

type RestackConflictPolicy int

RestackConflictPolicy controls what RunRestack does when a branch conflicts.

const (
	// RestackConflictEnterWorkflow stops at the first conflict and leaves the
	// repository mid-rebase for `stackit continue`.
	RestackConflictEnterWorkflow RestackConflictPolicy = iota

	// RestackConflictReport restacks every stack that applies cleanly and
	// reports conflicts without writing rebase state. Use it wherever nobody
	// can resolve a conflict interactively: JSON output, parallel workers, and
	// any caller that is not attached to a terminal.
	RestackConflictReport

	// RestackConflictPrompt reports like RestackConflictReport, then asks the
	// request's Prompter whether to resolve the first conflict now.
	RestackConflictPrompt
)

type RestackConflictPrompter added in v0.30.1

type RestackConflictPrompter interface {
	IsInteractive() bool
	PromptResolveConflicts(conflictBranches []string) (bool, error)
}

RestackConflictPrompter asks whether to resolve restack conflicts now. It is consulted only under RestackConflictPrompt.

type RestackDeps added in v0.30.1

type RestackDeps struct {
	Engine    engine.Engine
	Out       output.Output
	Log       output.Logger
	RepoRoot  string
	Snapshots Snapshots
	// Interactive and Quiet mirror the global flags; together with the
	// terminal they decide whether RestackAction may prompt to enable rerere.
	Interactive bool
	Quiet       bool
}

RestackDeps are the collaborators the restack command pipeline (PlanRestack, RestackAction, RunRestack) needs.

type RestackHandler added in v0.30.1

type RestackHandler interface {
	// OnRestackStart is called at the beginning of restack with branch count
	OnRestackStart(branchCount int)

	// OnRestackBranch is called for each branch during restack.
	OnRestackBranch(event RestackBranchEvent)

	// OnRestackComplete is called when restack finishes. blocked lists
	// branches left untouched because their stack contained a conflict.
	OnRestackComplete(summary RestackSummary)
}

RestackHandler receives restack progress. Every command that restacks (restack, sync, get, submit) reports through it via RunRestack, so adapters render one event shape regardless of which command produced it.

type RestackOptions

type RestackOptions struct {
	BranchName         string
	Scope              engine.StackRange
	AllStacks          bool
	StackRoots         []string
	ContinueOnConflict bool
	Parallel           bool // Run independent stack groups in parallel worktrees
	Jobs               int  // Number of parallel workers (0 = NumCPU)
	// NonInteractive suppresses every prompt and reports conflicts instead of
	// entering the conflict workflow. Set it for machine-readable output: the
	// workflow prints human guidance and leaves the repository mid-rebase.
	NonInteractive bool
}

RestackOptions contains options for the restack command

type RestackOutcome added in v0.30.1

type RestackOutcome struct {
	Summary RestackSummary
	// EnteredConflictWorkflow is true when the user chose to resolve a
	// conflict and the run handed off to the conflict workflow. The handler's
	// OnRestackComplete is not called in that case: the restack is unfinished.
	EnteredConflictWorkflow bool
}

RestackOutcome is the result of RunRestack.

func RunRestack added in v0.30.1

func RunRestack(ctx context.Context, deps RestackDeps, req RestackRequest, handler RestackHandler) (RestackOutcome, error)

RunRestack is the restack pipeline every command shares: it enables rerere, executes the groups sequentially or in parallel, reports each branch to handler as a RestackBranchEvent, and applies the conflict policy.

Worktree holds and snapshots are the caller's responsibility, because the commands disagree on scope: restack and sync filter holds before choosing branches, and only some callers have a rollback point worth taking.

type RestackPlan

type RestackPlan struct {
	// contains filtered or unexported fields
}

RestackPlan is the precomputed work for a restack operation. Build it via PlanRestack, inspect via HasBranches/HasWork, then pass it to RestackAction.

Sharing the plan between the CLI's "is there work?" gate and the action itself avoids running engine.PlanRestack twice — that's ~3 git operations per branch, ~10ms/branch on a warm filesystem.

func PlanRestack

func PlanRestack(ctx context.Context, deps RestackDeps, opts RestackOptions) (*RestackPlan, error)

PlanRestack resolves the branch groups for opts and pre-computes the engine restack plan for each group. Pass the result to RestackAction to skip recomputing those plans during execution.

The per-group engine plan is *not* reused in parallel mode — each worktree has its own engine and must compute its own plan against worktree-local state.

func (*RestackPlan) BranchCount

func (p *RestackPlan) BranchCount() int

BranchCount returns the total number of branches across all groups.

func (*RestackPlan) HasBranches

func (p *RestackPlan) HasBranches() bool

HasBranches reports whether any branch was resolved from the requested scope. False means the scope is empty (e.g. on trunk with no children).

func (*RestackPlan) HasWork

func (p *RestackPlan) HasWork() bool

HasWork reports whether any resolved branch needs an actual rebase. Branches that are up-to-date, locked, or frozen do not count.

type RestackRequest added in v0.30.1

type RestackRequest struct {
	// Branches is restacked as a single group, in topological order.
	Branches engine.Branches

	ConflictPolicy RestackConflictPolicy
	// Prompter is consulted under RestackConflictPrompt. A nil or
	// non-interactive prompter reports conflicts instead.
	Prompter RestackConflictPrompter

	// PromptRerere allows asking the user before enabling git rerere.
	PromptRerere bool
	// Pauser releases the terminal around the rerere prompt. nil uses the
	// handler when it implements rerere.Pauser.
	Pauser rerere.Pauser

	// Parallel runs independent groups in separate worktrees. It only applies
	// when there is more than one group, and always reports conflicts.
	Parallel bool
	Jobs     int // parallel workers; 0 means NumCPU

	// PRNumber overrides the PR lookup for event enrichment. nil reads the
	// branch's local metadata.
	PRNumber func(branch string) *git.PRNumber
	// contains filtered or unexported fields
}

RestackRequest describes one restack run. Callers decide which branches to restack; RunRestack owns everything after that.

type RestackResult added in v0.30.1

type RestackResult string

RestackResult represents the outcome of a restack operation for a single branch

const (
	// RestackDone indicates the branch was successfully restacked
	RestackDone RestackResult = "done"
	// RestackUnneeded indicates the branch didn't need restacking
	RestackUnneeded RestackResult = "unneeded"
	// RestackConflict indicates the branch had a conflict
	RestackConflict RestackResult = "conflict"
	// RestackBlocked indicates the branch was left untouched because another
	// branch in its stack conflicted
	RestackBlocked RestackResult = "blocked"
)

type RestackSummary added in v0.30.1

type RestackSummary struct {
	Restacked int
	Conflicts []string // branches skipped because they conflicted
	Blocked   []string
}

RestackSummary contains aggregate outcomes from a restack operation.

type RestackWorktreeHold added in v0.25.0

type RestackWorktreeHold struct {
	Scope        RestackWorktreeHoldScope
	Branch       string
	StackRoot    string
	WorktreePath engine.WorktreePath
	Reason       string
}

RestackWorktreeHold describes a worktree that prevents a branch or stack from being safely restacked. It is read-only diagnostic data; callers must never move refs or reset worktrees in response to it.

func ManagedWorktreeHolds added in v0.30.1

func ManagedWorktreeHolds(ctx context.Context, eng ManagedWorktreeSource) ([]RestackWorktreeHold, error)

ManagedWorktreeHolds returns a stack-scoped hold for every managed worktree whose checkout cannot be safely reset, in registry order. sync's --dry-run preview calls it directly so the preview cannot promise work the run skips.

func (RestackWorktreeHold) Warning added in v0.30.1

func (h RestackWorktreeHold) Warning() string

Warning renders the hold as the line printed before a restack runs.

type RestackWorktreeHoldReport added in v0.25.0

type RestackWorktreeHoldReport struct {
	Holds    []RestackWorktreeHold
	Warnings []string
}

RestackWorktreeHoldReport contains the holds that affect a restack and warnings from worktree inspection that could not produce a specific hold.

func CollectRestackWorktreeHolds added in v0.30.1

func CollectRestackWorktreeHolds(ctx context.Context, eng engine.Engine) RestackWorktreeHoldReport

CollectRestackWorktreeHolds inspects every physical checkout and reports the branches and stacks a restack must leave alone. sync and restack both read this one report, so they hold back exactly the same work.

func (RestackWorktreeHoldReport) Filter added in v0.30.1

Filter drops every branch a hold covers, preserving order.

func (RestackWorktreeHoldReport) Messages added in v0.30.1

func (r RestackWorktreeHoldReport) Messages() []string

Messages returns one human-readable line per hold and per inspection warning, for adapters to print before the restack runs.

type RestackWorktreeHoldScope added in v0.25.0

type RestackWorktreeHoldScope string

RestackWorktreeHoldScope describes the work that a hold prevents.

const (
	// RestackWorktreeHoldStack prevents restacking every branch in a stack.
	RestackWorktreeHoldStack RestackWorktreeHoldScope = "stack"
	// RestackWorktreeHoldBranch prevents restacking only one branch.
	RestackWorktreeHoldBranch RestackWorktreeHoldScope = "branch"
)

type ReviewStatus added in v0.22.0

type ReviewStatus string

ReviewStatus is the PR review state reported in tree JSON output.

const (
	ReviewApproved         ReviewStatus = "approved"
	ReviewChangesRequested ReviewStatus = "changes_requested"
	ReviewRequired         ReviewStatus = "review_required"
)

Review status values for TreePRInfo.

type RewriteGuard added in v0.29.0

type RewriteGuard struct {
	// contains filtered or unexported fields
}

RewriteGuard restores the original branch when a branch-rewriting operation fails, so the user is never left on a detached HEAD.

Typical use:

guard, err := actions.DetachForRewrite(ctx, eng, branch)
if err != nil {
	return err
}
defer guard.RestoreUnlessReleased(ctx, &err) // err is a named result
...
guard.Release()
return nil

Restoring runs, in order: cleanup hooks registered with OnRestore (last registered first), a reset of the branch ref when RestoreRefTo was called, then a force checkout of the branch. A restore failure never masks the operation's error: it is appended to it along with a recovery command.

func DetachForRewrite added in v0.29.0

func DetachForRewrite(ctx context.Context, eng detachForRewriteEngine, branch engine.Branch) (*RewriteGuard, error)

DetachForRewrite detaches HEAD and resets the branch's changes into the working tree, returning a guard that restores the branch on failure.

func NewRewriteGuard added in v0.29.0

func NewRewriteGuard(eng rewriteGuardEngine, branch engine.Branch) *RewriteGuard

NewRewriteGuard returns a guard for an operation that detaches HEAD itself (for example engine.ApplySplitToCommits).

func (*RewriteGuard) OnRestore added in v0.29.0

func (g *RewriteGuard) OnRestore(hook func())

OnRestore registers cleanup that must run before the branch is restored, such as popping a stash or deleting a partially created branch. Hooks run in reverse registration order, like defers.

func (*RewriteGuard) Release added in v0.29.0

func (g *RewriteGuard) Release()

Release disarms the guard. Call it once the rewrite has succeeded, or once it has reached a state that must be left in place for manual recovery.

func (*RewriteGuard) Restore added in v0.29.0

func (g *RewriteGuard) Restore(ctx context.Context, opErr error) error

Restore puts the branch back now and returns opErr, annotated with recovery guidance if restoring failed. The guard is released afterwards so a deferred RestoreUnlessReleased does not restore twice.

func (*RewriteGuard) RestoreRefTo added in v0.29.0

func (g *RewriteGuard) RestoreRefTo(sha string)

RestoreRefTo records the SHA the branch ref must be reset to on restore. Call it once the operation has moved the branch ref.

func (*RewriteGuard) RestoreUnlessReleased added in v0.29.0

func (g *RewriteGuard) RestoreUnlessReleased(ctx context.Context, errp *error)

RestoreUnlessReleased restores the branch unless Release was called. Pass a pointer to the caller's named error result; a restore failure is added to it.

type SnapshotEngine added in v0.30.1

type SnapshotEngine interface {
	TakeSnapshot(ctx context.Context, opts engine.SnapshotOptions) error
	ClearLastSnapshotID()
}

SnapshotEngine is the engine surface undo snapshots use.

type SnapshotOption

type SnapshotOption func(*engine.SnapshotOptions)

SnapshotOption is a function that modifies SnapshotOptions

func WithArg

func WithArg(arg string) SnapshotOption

WithArg appends a single argument if it's not empty

func WithArgs

func WithArgs(args ...string) SnapshotOption

WithArgs appends multiple arguments

func WithFlag

func WithFlag(condition bool, flag string) SnapshotOption

WithFlag appends a flag if condition is true

func WithFlagValue

func WithFlagValue(flag string, value string) SnapshotOption

WithFlagValue appends a flag with a value if the value is not empty

func WithWorktreeCapture added in v0.28.0

func WithWorktreeCapture(capture engine.WorktreeCapture) SnapshotOption

WithWorktreeCapture records uncommitted changes with the snapshot, so a later abort or undo can hand them back. Use it on commands that turn the working tree into a commit — modify, create, absorb, split — and nowhere else.

Pick the cheapest level that covers what this invocation stages. Only staging everything (`git add -A`) turns an untracked file into a commit; `-u` and `-p` never touch untracked files, and anything the user staged themselves is already in the tracked (stash) capture. The untracked level hashes every untracked file, so it is wasted anywhere else.

type Snapshots added in v0.30.1

type Snapshots struct {
	Engine SnapshotEngine
	// Enabled reflects undo.enabled.
	Enabled bool
	Log     DebugLogger
}

Snapshots records the undo snapshot a mutating command takes before it changes anything.

func (Snapshots) Take added in v0.30.1

func (s Snapshots) Take(ctx context.Context, opts engine.SnapshotOptions)

Take records an undo snapshot and logs failures without aborting the action. When undo is disabled, it clears the rollback binding without writing a snapshot.

type StackInfoBranch added in v0.23.0

type StackInfoBranch struct {
	Name           string
	Parent         string
	IsLocked       bool
	IsFrozen       bool
	Scope          string
	PRNumber       *git.PRNumber
	PRURL          string
	CommitMessages []string
	DiffStats      BranchDiffStats
}

StackInfoBranch is structured info for one non-trunk branch in a stack.

type StackInfoResult added in v0.23.0

type StackInfoResult struct {
	StackTitle       string
	StackDescription string
	Current          string
	Trunk            string
	Branches         []StackInfoBranch // non-trunk branches, in stack order
	Order            []string          // every branch name (incl trunk), in stack order
	Parents          map[string]string // branch -> parent (incl trunk)
	UpToDate         map[string]bool   // branch -> up to date with parent (incl trunk)
}

StackInfoResult contains structured data for `stackit info --stack`. It carries both the per-branch annotations (Branches) and the stack shape needed to draw the tree (Order/Parents/UpToDate), all as plain data — the CLI adapter turns it into a tree widget or JSON.

func QueryStackInfo added in v0.23.0

func QueryStackInfo(ctx context.Context, eng engine.Engine) (StackInfoResult, error)

QueryStackInfo gathers structured information about the current stack.

type TopologyEngine added in v0.30.1

type TopologyEngine interface {
	Graph(ctx context.Context, strategy engine.SortStrategy) *engine.StackGraph
	AllBranches() engine.Branches
	IsTrunk(branch engine.Branch) bool
}

TopologyEngine is the engine surface the linear-stack check reads.

type TreeBranchInfo added in v0.20.0

type TreeBranchInfo struct {
	Name      string `json:"name"`
	Parent    string `json:"parent,omitempty"`
	IsCurrent bool   `json:"is_current"`
	IsTrunk   bool   `json:"is_trunk"`
	// Status booleans are always emitted (no omitempty) so consumers can rely on
	// `tree --json` as a complete, self-describing status source: an explicit
	// false is unambiguous, whereas an omitted field is indistinguishable from
	// "this field isn't reported". This is what lets agents read PR/CI status and
	// needs_restack/locked/frozen from a single command instead of also querying
	// `info --stack --json`.
	IsLocked     bool        `json:"is_locked"`
	IsFrozen     bool        `json:"is_frozen"`
	NeedsRestack bool        `json:"needs_restack"`
	Commits      *int        `json:"commits,omitempty"`
	Additions    int         `json:"additions,omitempty"`
	Deletions    int         `json:"deletions,omitempty"`
	PR           *TreePRInfo `json:"pr,omitempty"`
	Scope        string      `json:"scope,omitempty"`
	Children     []string    `json:"children,omitempty"`
}

TreeBranchInfo represents a single branch in JSON output

type TreeJSONRequest added in v0.29.0

type TreeJSONRequest struct {
	Style TreeStyle
	// Branches, when non-nil, bounds the result to exactly these branches.
	// Adapters resolve it with the text renderer's visibility rules (--stack
	// scope, --steps depth, anchor flattening) so JSON matches the text view
	// and enrichment only runs for branches the view would draw. Nil reports
	// every tracked branch.
	Branches engine.Branches
}

TreeJSONRequest selects what BuildTreeJSON reports.

type TreeJSONResult added in v0.20.0

type TreeJSONResult struct {
	Branches        []TreeBranchInfo `json:"branches"`
	Summary         TreeSummary      `json:"summary"`
	GitHubAvailable *bool            `json:"github_available,omitempty"`
}

TreeJSONResult represents the JSON output for the tree command

func BuildTreeJSON added in v0.20.0

func BuildTreeJSON(ctx context.Context, eng engine.Engine, gh github.Client, req TreeJSONRequest) TreeJSONResult

BuildTreeJSON builds the structured tree result (branch tree, PR/CI status, and per-branch health) without printing it, so other commands — e.g. `state` — can embed the same stack snapshot. Short views omit statistics and PR data; normal/full JSON retain the complete historical contract, including CI.

gh may be nil when GitHub is unavailable. Short views never use it, so callers should not construct a client for them.

type TreeOptions added in v0.20.0

type TreeOptions struct {
	Style         TreeStyle
	Steps         *int
	BranchName    string
	ShowUntracked bool
	Interactive   bool
	ShowSHAs      bool // Show commit SHAs next to branch names
	JSON          bool // Output in JSON format
}

TreeOptions contains options for the tree command

type TreePRInfo added in v0.20.0

type TreePRInfo struct {
	Number       git.PRNumber `json:"number"`
	URL          string       `json:"url,omitempty"`
	Title        string       `json:"title,omitempty"`
	State        git.PRState  `json:"state"`
	IsDraft      bool         `json:"is_draft,omitempty"`
	ReviewStatus ReviewStatus `json:"review_status,omitempty"`
	CIStatus     string       `json:"ci_status,omitempty"`
}

TreePRInfo represents PR information in JSON output

type TreeStyle added in v0.22.0

type TreeStyle string

TreeStyle defines the output style for the tree command

const (
	TreeStyleNormal TreeStyle = "NORMAL"
	TreeStyleFull   TreeStyle = "FULL"
	TreeStyleShort  TreeStyle = "SHORT"
)

type TreeSummary added in v0.20.0

type TreeSummary struct {
	TotalBranches int  `json:"total_branches"`
	ApprovedCount *int `json:"approved_count,omitempty"`
	InReviewCount *int `json:"in_review_count,omitempty"`
}

TreeSummary represents summary statistics in JSON output

type Warner added in v0.30.1

type Warner interface {
	Warn(format string, args ...any)
}

Warner receives user-facing warnings. output.Output satisfies it.

type WorktreeOwners added in v0.28.0

type WorktreeOwners struct {
	// contains filtered or unexported fields
}

WorktreeOwners answers OwningWorktree for many branches from one listing of worktree registrations.

func LoadWorktreeOwners added in v0.28.0

func LoadWorktreeOwners(ctx context.Context, eng OwnershipEngine) (WorktreeOwners, error)

LoadWorktreeOwners reads every worktree registration once.

func (WorktreeOwners) Owner added in v0.28.0

func (o WorktreeOwners) Owner(branch engine.Branch) (*engine.WorktreeInfo, error)

Owner returns the managed worktree that owns branch's stack, or nil for an ordinary stack. A malformed registration is an error, never "unowned", so guards fail closed.

Directories

Path Synopsis
Package abort implements the stackit abort command for canceling in-progress operations.
Package abort implements the stackit abort command for canceling in-progress operations.
Package absorb provides functionality for absorbing staged changes into commits downstack.
Package absorb provides functionality for absorbing staged changes into commits downstack.
Package checkout implements the stackit checkout command: resolving a target branch, switching worktrees when the branch lives elsewhere, and checking it out.
Package checkout implements the stackit checkout command: resolving a target branch, switching worktrees when the branch lives elsewhere, and checking it out.
Package create provides functionality for creating new stacked branches.
Package create provides functionality for creating new stacked branches.
Package debug implements the debug command, which dumps stack, snapshot, continuation, and remote metadata state as JSON for troubleshooting.
Package debug implements the debug command, which dumps stack, snapshot, continuation, and remote metadata state as JSON for troubleshooting.
Package delete provides functionality for deleting branches and their metadata.
Package delete provides functionality for deleting branches and their metadata.
Package describe implements the stackit describe command for managing stack descriptions.
Package describe implements the stackit describe command for managing stack descriptions.
Package doctor provides diagnostic functionality for checking stackit environment and repository health.
Package doctor provides diagnostic functionality for checking stackit environment and repository health.
Package flatten provides functionality for flattening stacked branches closer to trunk.
Package flatten provides functionality for flattening stacked branches closer to trunk.
Package fold provides functionality for folding stacked branches.
Package fold provides functionality for folding stacked branches.
Package foreach provides functionality for executing a command on each branch in a stack.
Package foreach provides functionality for executing a command on each branch in a stack.
Package freeze implements the freeze and unfreeze commands, which stop (and resume) restacking for a branch and the branches it depends on or that depend on it.
Package freeze implements the freeze and unfreeze commands, which stop (and resume) restacking for a branch and the branches it depends on or that depend on it.
Package get implements the get command, which fetches a branch (or a PR's head branch) and its stack from the remote and tracks it locally.
Package get implements the get command, which fetches a branch (or a PR's head branch) and its stack from the remote and tracks it locally.
Package handler provides common handler types and base implementations for action handlers throughout the stackit codebase.
Package handler provides common handler types and base implementations for action handlers throughout the stackit codebase.
Package hooks orchestrates hook discovery, approval, and execution at the actions layer.
Package hooks orchestrates hook discovery, approval, and execution at the actions layer.
Package init provides functionality for initializing Stackit in a Git repository.
Package init provides functionality for initializing Stackit in a Git repository.
Package integrations provides functionality for integrating Stackit with external tools and hooks.
Package integrations provides functionality for integrating Stackit with external tools and hooks.
Package lock provides functionality for locking and unlocking branches in a stack.
Package lock provides functionality for locking and unlocking branches in a stack.
Package merge provides functionality for merging stacked pull requests.
Package merge provides functionality for merging stacked pull requests.
Package modify implements the modify command, which amends (or adds) a commit on the current branch or a downstack ancestor and restacks its descendants.
Package modify implements the modify command, which amends (or adds) a commit on the current branch or a downstack ancestor and restacks its descendants.
Package move provides functionality for moving branches to different parents in the stack.
Package move provides functionality for moving branches to different parents in the stack.
Package navigation implements the stackit top/bottom commands for navigating stacked branches.
Package navigation implements the stackit top/bottom commands for navigating stacked branches.
Package openpr implements the pr command, which opens a branch's pull request in the default browser.
Package openpr implements the pr command, which opens a branch's pull request in the default browser.
Package pluck provides functionality for extracting a single branch from a stack.
Package pluck provides functionality for extracting a single branch from a stack.
Package pop implements the pop command: delete the current branch while keeping its changes staged on the parent.
Package pop implements the pop command: delete the current branch while keeping its changes staged on the parent.
Package rename implements the rename command, which renames the current branch and updates the stack metadata referencing it.
Package rename implements the rename command, which renames the current branch and updates the stack metadata referencing it.
Package reorder implements the reorder command, which reorders the branches between trunk and the current branch and restacks their descendants.
Package reorder implements the reorder command, which reorders the branches between trunk and the current branch and restacks their descendants.
Package restack is the core of every command that rebases branches onto their parents.
Package restack is the core of every command that rebases branches onto their parents.
Package scope implements the stackit scope command for managing branch scopes.
Package scope implements the stackit scope command for managing branch scopes.
Package share implements the share command, which renders the current stack as Slack-flavored markdown for copy-pasting.
Package share implements the share command, which renders the current stack as Slack-flavored markdown for copy-pasting.
Package split provides functionality for splitting stacked branches.
Package split provides functionality for splitting stacked branches.
Package squash implements the squash command, which squashes a branch's commits into one and restacks its upstack branches.
Package squash implements the squash command, which squashes a branch's commits into one and restacks its upstack branches.
Package stacklog gathers the current stack's commit band for the stack-aware `stackit log` view: the commits on the branch you're standing on and its ancestors down to (but not including) trunk, ordered top-down from HEAD.
Package stacklog gathers the current stack's commit band for the stack-aware `stackit log` view: the commits on the branch you're standing on and its ancestors down to (but not including) trunk, ordered top-down from HEAD.
Package stackview builds read-only view models of the stack — the managed worktree index and per-branch display annotations — for adapters (CLI, TUI, API) to render.
Package stackview builds read-only view models of the stack — the managed worktree index and per-branch display annotations — for adapters (CLI, TUI, API) to render.
Package state implements the state command, a single machine-readable snapshot of the stack, working tree, and any in-progress operation.
Package state implements the state command, a single machine-readable snapshot of the stack, working tree, and any in-progress operation.
Package submit provides functionality for submitting stacked branches as pull requests.
Package submit provides functionality for submitting stacked branches as pull requests.
Package sync provides functionality for synchronizing stacked branches with remote repositories.
Package sync provides functionality for synchronizing stacked branches with remote repositories.
Package track implements the stackit track command for tracking branches in a stack.
Package track implements the stackit track command for tracking branches in a stack.
Package trunklog gathers stack-aware trunk commit history for the `stackit log` command.
Package trunklog gathers stack-aware trunk commit history for the `stackit log` command.
Package undo provides functionality for undoing stackit operations using snapshots.
Package undo provides functionality for undoing stackit operations using snapshots.
Package untrack implements the stackit untrack command for stopping branch tracking.
Package untrack implements the stackit untrack command for stopping branch tracking.
Package validation provides reusable precondition validators for actions.
Package validation provides reusable precondition validators for actions.
Package worktree provides actions for managing stackit-managed worktrees.
Package worktree provides actions for managing stackit-managed worktrees.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL