mergequeue

package
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package mergequeue serializes git merges of task branches back to a base branch. Multiple parallel tasks can produce divergent commits on independent worktree branches; the merge queue drains them one at a time so each merge sees a clean, up-to-date base and conflicts (if any) surface against a well-defined parent.

Usage:

q := mergequeue.New(repoDir, baseBranch)
q.Start(ctx)
defer q.Stop()
res := q.Submit(mergequeue.Request{Branch: "cloop/task-42-foo", TaskID: 42})
<-res.Done
if res.Err != nil { ... }

A single internal goroutine processes requests in FIFO order so the merges happen one after the other without conflicts (each subsequent merge sees the previous merge's commits already on the base branch).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ConflictFile

type ConflictFile struct {
	Path    string
	Content string
}

ConflictFile is one entry in the set the Resolver is asked to fix. Content is the on-disk file with `<<<<<<<`, `=======`, `>>>>>>>` markers intact.

type Queue

type Queue struct {
	RepoDir    string
	BaseBranch string

	// MergeTimeout bounds how long any single git merge / abort step is allowed
	// to run. Defaults to 2 minutes when zero.
	MergeTimeout time.Duration
	// contains filtered or unexported fields
}

Queue serializes git merges back to BaseBranch.

func New

func New(repoDir, baseBranch string) *Queue

New returns a Queue ready to be Start()ed. baseBranch is the branch that all task branches are merged back into.

func (*Queue) SetResolver

func (q *Queue) SetResolver(r Resolver)

SetResolver installs an automatic conflict resolver. Pass nil to remove a previously-installed resolver. Safe to call before or after Start; the worker reads the field under a mutex on each merge.

func (*Queue) Start

func (q *Queue) Start(ctx context.Context)

Start launches the background worker. Safe to call once. If ctx is cancelled the worker drains in-flight submissions and exits.

func (*Queue) Stop

func (q *Queue) Stop()

Stop signals the worker to drain and exit. Blocks until the worker has finished. Safe to call multiple times.

func (*Queue) Submit

func (q *Queue) Submit(req Request) *Result

Submit enqueues a merge request. The returned Result.Done channel is closed when the merge has been attempted. If the queue has been stopped, the result is returned pre-closed with an error.

type Request

type Request struct {
	// Branch is the source branch to merge into BaseBranch (e.g. cloop/task-42-foo).
	Branch string
	// TaskID is the cloop task this branch corresponds to (for logging).
	TaskID int
	// Title is a short human-readable label used in the merge commit message.
	Title string
}

Request is a single merge job submitted to the queue.

type ResolveInfo

type ResolveInfo struct {
	BaseBranch   string
	SourceBranch string
	TaskID       int
	TaskTitle    string
}

ResolveInfo gives the Resolver the merge context it needs to make sensible choices when the two sides disagree on the same line.

type ResolvedFile

type ResolvedFile struct {
	Path    string
	Content string
}

ResolvedFile is the Resolver's verdict for a single ConflictFile. Path must match the input ConflictFile.Path; Content is the fully-merged file body with no conflict markers and ends with a newline.

type Resolver

type Resolver interface {
	Resolve(ctx context.Context, info ResolveInfo, files []ConflictFile) ([]ResolvedFile, error)
}

Resolver attempts to automatically resolve a git merge conflict.

The Queue calls Resolve after `git merge` reports a conflict and before running `git merge --abort`. The implementation receives the list of conflicted files (with conflict markers intact) and returns the resolved contents for any file it was able to handle. The Queue then writes those files back, stages them, and finishes the merge via `git commit`. If Resolve returns an error, returns fewer resolutions than conflicts, or any resolution still contains conflict markers, the Queue aborts the merge so the original "leave branch for manual resolution" behaviour is preserved.

Implementations must be safe for concurrent calls — the Queue serializes merges itself, but a Resolver may be shared across queues.

type Result

type Result struct {
	// Done is closed once the merge has been attempted.
	Done chan struct{}
	// Err is nil on success, or describes the merge failure (conflict, abort, etc.).
	// Safe to read after Done is closed.
	Err error
	// CommitSHA is the SHA of the merge commit (or "" when nothing was merged).
	CommitSHA string
}

Result reports the outcome of a single merge. Callers wait on Done.

Jump to

Keyboard shortcuts

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