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

sync

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: 21 Imported by: 0

Documentation

Overview

Package sync provides functionality for synchronizing stacked branches with remote repositories.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Action

func Action(ctx context.Context, deps Deps, opts Options, handler Handler) error

Action performs the sync operation

Types

type Config added in v0.30.1

type Config interface {
	WorktreeAutoClean() bool
}

Config lists the configuration getters sync reads. A nil Config behaves as if no configuration was loaded.

type Deps added in v0.30.1

type Deps struct {
	// Engine is the full engine: sync reconciles the whole repository —
	// trunk, remote and stack metadata, PR info, worktrees, branch cleanup —
	// so the surface it touches spans nearly every engine role, and the
	// restack and cleanup pipelines it delegates to take engine.Engine too.
	Engine engine.Engine
	Out    output.Output
	Log    output.Logger
	// GitHub returns the client, or nil when GitHub is unavailable. It is a
	// function so the client is only built when sync actually needs it.
	GitHub func() github.Client
	// GHRunner runs the GraphQL queries that fetch PR info.
	GHRunner github.GitCommandRunner
	// PRSync refreshes PR footers and titles for flagged branches and pushes
	// orphaned metadata the user chose to keep.
	PRSync actions.PRSync
	// Restack is what the restack phase runs actions.RunRestack with. Its
	// Interactive and Quiet flags also decide whether sync may prompt to
	// enable rerere.
	Restack actions.RestackDeps
	// Cleanup is what the merged/closed branch cleanup phase runs with.
	Cleanup   actions.CleanBranchesDeps
	Snapshots actions.Snapshots
	// Here is where sync runs; a managed worktree never removes itself and
	// cannot delete branches checked out elsewhere.
	Here   actions.Here
	Config Config
}

Deps are the collaborators sync needs. Adapters build them from their own runtime state; the action never sees bootstrap types.

type DryRunCleanItem added in v0.29.0

type DryRunCleanItem struct {
	Branch string
	Reason string // e.g. "merged into main", "closed on GitHub"
}

DryRunCleanItem is a branch a sync would delete, with the reason.

type DryRunPlan added in v0.29.0

type DryRunPlan struct {
	PullBranch        string              // trunk that would be pulled (empty if up to date)
	PullRevision      string              // short remote SHA the trunk would move to
	Clean             []DryRunCleanItem   // branches that would be deleted
	Restack           []DryRunRestackItem // branches that would be restacked
	RestackStacks     []string            // deduped stack roots covering the restack set (JSON only)
	SkippedStacks     []string            // dirty-worktree anchors whose stacks are skipped
	RestackRequested  bool                // whether --restack was requested
	TrunkStateUnknown bool                // trunk's remote relationship could not be resolved
}

DryRunPlan is the read-only snapshot of what a sync WOULD do, built from the current (remote-aware) state. It carries enough detail to render a preview that mirrors the live run — target revision, deletion reasons, restack parents. The JSON contract is a stable, names-only projection (see Result); the richer fields exist only to make the human-readable preview as informative as the real sync.

func PlanDryRun added in v0.29.0

func PlanDryRun(ctx context.Context, eng PlanEngine, req PlanRequest) DryRunPlan

PlanDryRun builds a read-only snapshot of what a sync WOULD do from the current (remote-aware) state. It never mutates: it probes remote status and reads PR/deletion state, but performs no fetch-and-merge, deletion, restack, or GitHub write. It is a query rather than a simulation of Action with a special handler; the dirty-worktree skip decision is shared with Action via actions.ManagedWorktreeHolds so the preview cannot promise work the run then skips.

ctx should be the bounded remote-operation context so every remote-status and deletion read shares one deadline.

func (DryRunPlan) Result added in v0.29.0

func (p DryRunPlan) Result() DryRunResult

Result projects the plan onto the stable JSON contract (branch names only). The shape is byte-compatible with what scripts already consume, so the richer preview fields are deliberately dropped here.

type DryRunRestackItem added in v0.29.0

type DryRunRestackItem struct {
	Branch string
	Parent string
}

DryRunRestackItem is a branch a sync would restack onto Parent.

type DryRunResult

type DryRunResult struct {
	WouldPull          string   `json:"would_pull,omitempty"`           // Trunk branch that would be pulled
	WouldClean         []string `json:"would_clean,omitempty"`          // Branches that would be deleted
	WouldRestack       []string `json:"would_restack,omitempty"`        // Branches that would be restacked
	WouldRestackStacks []string `json:"would_restack_stacks,omitempty"` // Deduped independent stack roots covering the current dry-run's would_restack set; recompute after sync before passing to `restack --stacks <roots>` because cleanup/reparenting can change roots
	SkippedStacks      []string `json:"skipped_stacks,omitempty"`       // Stacks skipped due to dirty worktrees
	TrunkStateUnknown  bool     `json:"trunk_state_unknown,omitempty"`  // Trunk's relationship to its remote could not be resolved (objects not fetched); an absent would_pull does NOT mean trunk is current
}

DryRunResult represents the JSON output for sync --dry-run

type Event

type Event struct {
	Phase       Phase         // Current phase
	Type        EventType     // Event type
	Branch      string        // Branch name (if applicable)
	PRNumber    *git.PRNumber // PR number (if applicable)
	Message     string        // Human-readable description
	OldRevision string        // For position changes
	NewRevision string        // For position changes
	Conflict    bool          // Is this a conflict?
	HeldBy      string        // Why a worktree held this branch back (empty if it was not held)
	Error       error         // If non-nil, this step had an error
}

Event represents a progress update during sync

type EventType

type EventType string

EventType represents the type of sync event

const (
	EventStarted   EventType = "started"
	EventProgress  EventType = "progress"
	EventCompleted EventType = "completed"
	EventSkipped   EventType = "skipped"
)

Event types for sync operations

type GitHubSyncResult

type GitHubSyncResult struct {
	BranchNames []string
	RepoOwner   string
	RepoName    string
	PRInfos     map[string]*github.PullRequestInfo
	// contains filtered or unexported fields
}

GitHubSyncResult holds the results from GitHub PR info sync (network operation)

type Handler

type Handler interface {
	// Start is called at the beginning of sync with the total operation count
	Start(totalOps int)

	// EmitEvent is called for each progress update
	EmitEvent(event Event)

	// Complete is called when sync finishes with the summary
	Complete(summary Summary)

	// Cleanup ensures terminal is restored on error (may be no-op for non-TTY handlers)
	Cleanup()

	// IsInteractive returns true if this handler supports interactive prompts.
	// Non-interactive handlers return false and their prompt methods return defaults.
	IsInteractive() bool

	// PromptMetadataConflict displays a metadata conflict and asks user to accept remote.
	// Returns true to accept remote metadata, false to keep local.
	// In non-interactive mode, returns (false, nil) to preserve local changes.
	PromptMetadataConflict(diff *engine.MetadataDiff) (acceptRemote bool, err error)

	// PromptOrphanedMetadata asks what to do when remote metadata was deleted but local has changes.
	// Returns true to push local metadata to remote, false to accept deletion.
	// In non-interactive mode, returns (false, nil) to accept the remote deletion.
	PromptOrphanedMetadata(info engine.OrphanedMetadataInfo) (pushLocal bool, err error)

	// PromptBranchDeletions displays planned branch deletions and asks user to confirm each one.
	// unpushedBranches identifies branches with local commits not yet pushed to remote.
	// Returns a map of branch names that the user confirmed for deletion.
	// In non-interactive mode, returns all branches except unpushed ones (which are skipped by default).
	PromptBranchDeletions(branches map[string]string, unpushedBranches map[string]bool) (confirmed map[string]bool, err error)

	// PromptResolveConflicts asks user if they want to resolve restack conflicts now or skip them.
	// Returns true to start conflict resolution workflow, false to skip and continue.
	// In non-interactive mode, returns (false, nil) to skip conflicts.
	PromptResolveConflicts(conflictBranches []string) (resolve bool, err error)

	// RestackHandler methods are available for restack-specific output
	// This allows the same handler to be used for standalone restack operations
	actions.RestackHandler
}

Handler abstracts TTY vs non-TTY output for sync operations It embeds actions.RestackHandler to provide a unified interface for operations that include restacking

type NullHandler

type NullHandler struct {
	handler.NullBase
	actions.NullRestackHandler
}

NullHandler is a no-op handler for testing or when output is not needed NullHandler is a no-op handler for when nil is passed. It embeds handler.NullBase for Cleanup() and IsInteractive(), and actions.NullRestackHandler for the restack-specific no-op methods.

func (*NullHandler) Complete

func (h *NullHandler) Complete(Summary)

Complete implements Handler.

func (*NullHandler) EmitEvent

func (h *NullHandler) EmitEvent(Event)

EmitEvent implements Handler.

func (*NullHandler) PromptBranchDeletions

func (h *NullHandler) PromptBranchDeletions(branches map[string]string, unpushedBranches map[string]bool) (map[string]bool, error)

PromptBranchDeletions implements Handler. Skips unpushed branches, auto-confirms the rest.

func (*NullHandler) PromptMetadataConflict

func (h *NullHandler) PromptMetadataConflict(_ *engine.MetadataDiff) (bool, error)

PromptMetadataConflict implements Handler. Returns false (keep local) in non-interactive mode.

func (*NullHandler) PromptOrphanedMetadata

func (h *NullHandler) PromptOrphanedMetadata(_ engine.OrphanedMetadataInfo) (bool, error)

PromptOrphanedMetadata implements Handler. Returns false (accept deletion) in non-interactive mode.

func (*NullHandler) PromptResolveConflicts

func (h *NullHandler) PromptResolveConflicts(_ []string) (bool, error)

PromptResolveConflicts implements Handler. Returns false (skip) in non-interactive mode.

func (*NullHandler) Start

func (h *NullHandler) Start(int)

Start implements Handler.

type Options

type Options struct {
	All          bool
	Force        bool
	Restack      bool // Explicitly restack the full current stack (opt-in)
	NoRestack    bool // Skip all restacking entirely
	DryRun       bool
	RestackScope []string // When non-nil, only restack these branches (skip current-branch expansion)
}

Options contains options for the sync command

type ParentsToGitHubResult

type ParentsToGitHubResult struct {
	BranchesUpdated []string // Branches whose PR base was updated on GitHub
}

ParentsToGitHubResult contains the result of pushing local parents to GitHub

func PushParentsToGitHub

func PushParentsToGitHub(ctx context.Context, deps Deps, result *GitHubSyncResult, dirtyAnchors dirtyAnchorSet) (*ParentsToGitHubResult, error)

PushParentsToGitHub pushes local parent relationships to GitHub PR bases. Local metadata is authoritative - if local parent differs from GitHub PR base, update GitHub.

type Phase

type Phase string

Phase represents the current phase of the sync operation

const (
	PhaseTrunk    Phase = "trunk"
	PhaseBranches Phase = "branches"
	PhaseGitHub   Phase = "github"
	PhaseClean    Phase = "clean"
	PhaseRestack  Phase = "restack"
)

Phases of the sync operation

type PlanEngine added in v0.29.0

type PlanEngine interface {
	actions.ManagedWorktreeSource
	Trunk() engine.Branch
	AllBranches() engine.Branches
	ReadBranchRemoteStatuses(ctx context.Context, branches engine.Branches) engine.BranchRemoteStatuses
	ReadBranchStatuses(ctx context.Context, branches engine.Branches) engine.BranchStatuses
	GetDeletionStatuses(ctx context.Context, branchNames []string) (engine.DeletionStatuses, error)
	GetStackRootForBranch(branch engine.Branch) string
}

PlanEngine is the read-only engine surface PlanDryRun needs.

type PlanRequest added in v0.29.0

type PlanRequest struct {
	// Restack previews restacking of every out-of-date tracked branch, as
	// `sync --restack` would.
	Restack bool
}

PlanRequest configures a dry-run sync plan.

type StackMetadataGCResult

type StackMetadataGCResult struct {
	DeletedStackIDs []string // Stack IDs whose refs were deleted
	Errors          []string // Any errors encountered (non-fatal)
}

StackMetadataGCResult contains the results of stack metadata garbage collection.

type Summary

type Summary struct {
	TrunkUpdated      bool     // Was trunk updated?
	TrunkRevision     string   // New trunk revision (short hash)
	BranchesSynced    int      // Number of branches synced from remote
	BranchesRestacked int      // Number of branches restacked
	BranchesDeleted   int      // Number of branches deleted
	BranchesSkipped   int      // Number of branches skipped (due to conflicts)
	ConflictBranches  []string // Names of branches that conflicted
	BranchesBlocked   int      // Number of branches left untouched because their stack conflicted
	UpToDate          bool     // Everything was already current
	WorktreesCleaned  int      // Number of orphaned worktrees cleaned up
	SkippedStacks     []string // Stacks skipped due to dirty worktrees
}

Summary holds aggregate results from a sync operation

func (*Summary) HasChanges

func (s *Summary) HasChanges() bool

HasChanges returns true if any operations were performed

type WorktreeCleanupResult

type WorktreeCleanupResult struct {
	RemovedWorktrees []string // Stack roots whose worktrees were removed
	Errors           []string // Any errors encountered (non-fatal)
}

WorktreeCleanupResult contains the results of worktree cleanup

Jump to

Keyboard shortcuts

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