worktree

package
v0.27.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Package worktree creates, starts, stops and removes project worktrees, and drives the docker stack that goes with each one.

Index

Constants

View Source
const StatusAdoptable = "adoptable"

StatusAdoptable is shown for a worktree git lists and wtm has not adopted. It stands where up and down would: such a worktree has no index, hence no stack of its own to be up or down.

View Source
const StatusUnknown = "-"

StatusUnknown is shown when docker did not answer in time. A listing is a read-only question about git and must never hang on an unresponsive daemon.

Variables

This section is empty.

Functions

func Adopt added in v0.10.0

func Adopt(ctx context.Context, o Options) error

Adopt gives a worktree wtm did not create everything it gives one it did: a stable index, provisioned .env files and compose overrides, a restored snapshot and a stack. It stays where it is: an agent may be working in it.

func Create

func Create(ctx context.Context, o Options) error

func Env added in v0.21.0

func Env(ctx context.Context, o Options) ([]string, error)

Env is the environment `wtm run` sets, for a shell or an editor to load once (`eval "$(wtm env)"`, direnv). The generated compose.override.yaml covers the project name and ports only: interpolated variables need this.

func Exec

func Exec(ctx context.Context, o Options, service string, command []string) error

Exec runs a command inside the worktree's application container. Doing it by hand means knowing the compose project name wtm derives, which is internal knowledge no user should need.

func Path

func Path(ctx context.Context, o Options) (string, error)

Path returns the worktree directory, so a shell can compose with it: `cd $(wtm path feat/x)`.

func Ports added in v0.19.0

func Ports(ctx context.Context, o Options) ([]string, error)

Ports returns the addresses `start` prints, for a process handed a stack it did not start. The profile it was started with is not recorded, so every published port is listed.

func Remove

func Remove(ctx context.Context, o Options) error

Remove stops the stack then removes the worktree, keeping the local branch.

func Run

func Run(ctx context.Context, o Options, command []string) error

Run is the counterpart of Exec: it stays on the machine, with the worktree as working directory, for editors, agents and anything else working on the files rather than in the running application.

func Start

func Start(ctx context.Context, o Options) error

Start brings an existing worktree's stack back up. Without it, restarting a stopped worktree means calling docker compose with the index wtm derives, which is exactly the internal knowledge this tool exists to hide.

func Stop

func Stop(ctx context.Context, o Options) error

Stop halts the stack's containers, keeping them for the next start, and leaves the worktree in place.

func Switch added in v0.26.0

func Switch(ctx context.Context, o Options) error

Switch moves the adopted worktree of the current directory to o.Branch and gives it a fresh stack, keeping its index and so its ports. Git goes first: a refused checkout leaves the old stack untouched. Rerunning finishes a switch that failed halfway, since the recorded path still names the old branch.

Types

type Entry

type Entry struct {
	stack.Worktree
	// Status is "up", "down", "adoptable" for a worktree wtm has not adopted,
	// or "-" when docker could not be reached.
	Status string
	// ComposeProject is what `docker compose -p` takes, empty until an index
	// is recorded: before that, docker holds the only name there is.
	ComposeProject string
}

func List

func List(ctx context.Context, o Options) ([]Entry, error)

List answers about every linked worktree, adopted or not: a worktree wtm has not adopted is precisely the one somebody has to name to adopt it, and it used to be the one the listing left out.

func (Entry) Adoptable added in v0.14.0

func (e Entry) Adoptable() bool

Adoptable says the entry is there to be seen and named, not to be addressed: with no index, `adopt` is the only verb that has anything to say to it.

func (Entry) BranchLabel added in v0.23.0

func (e Entry) BranchLabel() string

BranchLabel is the branch as a listing shows it, with where HEAD sits when it is detached: a blank there reads as a bug in wtm rather than as that.

type Options

type Options struct {
	Name         string // project name in the registry
	Project      config.Project
	Branch       string
	Base         string
	NoStart      bool
	NoPostCreate bool // skip the project's post_create on this create
	// RunAfter and ExecAfter are the commands of `create --run` and `create
	// --exec`, played once the create is done: the first on the host from the
	// worktree, the second in the container. Shell lines, never persisted.
	RunAfter  string
	ExecAfter string
	// Profile is the stack profile this start brings up, empty for the whole
	// stack. Deliberately not remembered: a worktree narrowed months ago, with
	// nothing on screen saying so, is a puzzle, and naming it again is one word.
	Profile string
	Force   bool // remove despite uncommitted tracked changes
	// Inferred says nobody named this branch: `wtm create` releasing a vanished
	// worktree's index acts on a guess, so it refuses to take down a stack that
	// still runs. A branch somebody typed or confirmed sweeps what it was asked to.
	Inferred   bool
	BackupsDir string
	Runner     execx.Runner
	Out        io.Writer
	Stack      *stack.Client
	Resolver   *index.Resolver // resolves and records each branch's stable index
	// Confirm asks a yes-or-no question, and is nil when nobody is there to
	// answer. Its only caller is the memory advisory, an average over the
	// running stacks: worth a question, never worth failing a create on.
	Confirm func(question string) bool
	// BaseFromHere says Base came from `create --from-here` rather than from the
	// project or the command line. An existing branch is checked out as-is and
	// ignores the base, so that combination is refused rather than logged.
	BaseFromHere bool
	// RenameTo is the name an adopted branch takes. Adoption is the only
	// moment a rename is free: the compose project name carries the branch, so
	// renaming once a stack exists orphans the stack it names.
	RenameTo string
	// ConfirmAdopt asks before writing into a worktree wtm did not create. It
	// is deliberately not Confirm: --ignore-memory answers the memory advisory
	// alone, and must not also wave through a write into somebody's checkout.
	ConfirmAdopt func(question string) bool
}

type RemovalKind added in v0.23.0

type RemovalKind int

RemovalKind says what a removal takes away, which one verb hides: an adopted worktree keeps its directory, a vanished one has none left to take.

const (
	// RemoveCreated takes the stack, its volumes and the directory wtm created.
	RemoveCreated RemovalKind = iota
	// RemoveAdopted takes the stack and wtm's own files, and leaves the checkout.
	RemoveAdopted
	// RemoveStale releases the index of a worktree that left outside wtm,
	// taking down whatever stack still stands at it.
	RemoveStale
	// RemoveAbandoned deletes a directory git no longer lists as a worktree.
	RemoveAbandoned
)

type RemovalPlan added in v0.23.0

type RemovalPlan struct {
	Kind RemovalKind
	// Path is the worktree, or the directory git forgot. Empty for RemoveStale.
	Path string
	// Index is the one the registry records, 0 when it holds none.
	Index      int
	Locked     bool
	LockReason string
	// Changes are the tracked changes of a created worktree, left unchecked
	// under Force: skipping that check is what --force is for.
	Changes string
	// contains filtered or unexported fields
}

RemovalPlan is what Remove would do with the same Options, found without changing anything: a caller can show it before asking, and Remove acts on it, so what calls for --force is decided in one place.

func InspectRemoval added in v0.23.0

func InspectRemoval(ctx context.Context, o Options) (RemovalPlan, error)

InspectRemoval asks git and the registry, never docker, and writes nothing. A branch with neither a worktree nor an index nor a directory left gets git's own answer, which names the worktrees that do exist.

func (RemovalPlan) RequiresForce added in v0.23.0

func (p RemovalPlan) RequiresForce() bool

RequiresForce says Remove refuses the plan unless Options.Force is set.

Jump to

Keyboard shortcuts

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