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

bisect

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package bisect finds the commit that introduced a drift: a binary search over the commits between a known good and a known bad state, run for every drift group on its own, with the outcome of each tested commit shared between the groups.

Index

Constants

View Source
const (
	EnvDir     = "DRIFTGATE_BISECT_DIR"     // the worktree, on the commit
	EnvCommit  = "DRIFTGATE_BISECT_COMMIT"  // the full hash of the commit
	EnvProject = "DRIFTGATE_BISECT_PROJECT" // the project folder (driftgate.yaml) inside the worktree
	EnvRepo    = "DRIFTGATE_BISECT_REPO"    // the user's checkout, e.g. to copy an ignored .env from
)

Environment variables the hooks get.

View Source
const (
	Found    = "found"      // one commit
	Range    = "range"      // one of several commits, the others between could not be tested
	AtGood   = "at-good"    // the group drifts already at the good commit
	NotAtBad = "not-at-bad" // the group does not drift at the bad commit
)

Status of the answer for one group.

Variables

View Source
var ErrEndpoint = errors.New("the good or the bad commit could not be tested")

ErrEndpoint means the good or the bad commit could not be tested.

Functions

func Hook

func Hook(ctx context.Context, dir string, argv, env []string, limit time.Duration, log io.Writer) error

Hook runs a command without a shell, from dir, with env added to the environment and a time limit. Its output goes to a file, not a pipe: a command that starts the application in the background leaves it running without holding the hook open. A hook that runs out of time is killed with everything it started (procx), so an application it was restarting does not go on serving the old build to the next test. The last lines are shown when it fails; the error does not repeat the command, which the caller names.

func Wait

func Wait(ctx context.Context, dir string, argv, env []string, limit time.Duration) error

Wait repeats the ready command until it succeeds or the time is up. Its output is not shown: failing is what it does until the application answers.

Types

type Answer

type Answer struct {
	Group  string
	Status string
	First  int // the first commit with the drift (Found), or the last of the range (Range)
	From   int // with Range: the first commit that may have introduced it
	// Unsteady lists tested commits that contradict the answer: the group
	// drifts before First, or does not drift at or after it. The search
	// assumes a drift stays once it appears; with these, the commit named
	// is one place where it appears, not necessarily the first.
	Unsteady []int
}

Answer for one group. Commits are indexes into the path: 0 is the good commit, the last index the bad one.

type Commit

type Commit struct {
	Hash    string `json:"hash"`
	Short   string `json:"short"`
	Subject string `json:"subject"`
	Author  string `json:"author"`
	Date    string `json:"date"`
}

Commit is one commit of the searched path.

type Probe

type Probe struct {
	Skip    string          // why the commit could not be tested (hook failed, application did not answer); empty when tested
	Present map[string]bool // groups (drift signatures) that drift at the commit
}

Probe is the outcome of one commit.

type Repo

type Repo struct {
	Dir string // top level of the user's checkout
}

Repo is the user's git repository. Nothing here changes its working tree, index or branch: commits are checked out in a separate worktree.

func Open

func Open(ctx context.Context, dir string) (Repo, error)

Open finds the repository that holds dir.

func (Repo) AddWorktree

func (r Repo) AddWorktree(ctx context.Context, commit string) (*Worktree, error)

AddWorktree checks out commit in a new worktree under the system's temporary folder.

func (Repo) Path

func (r Repo) Path(ctx context.Context, good, bad string) ([]Commit, error)

Path lists the commits from good to bad along the first parents: good first, bad last. A merge is one step; the search names the merge, and a second bisect over the merged branch can go further.

func (Repo) Resolve

func (r Repo) Resolve(ctx context.Context, rev string) (string, error)

Resolve turns a revision (a branch, tag, hash, HEAD~3) into a commit hash.

type Searcher

type Searcher struct {
	Last int                        // index of the bad commit; the good one is 0
	Test func(i int) (Probe, error) // an error stops the search
	// contains filtered or unexported fields
}

Searcher tests commits through Test, at most once each, and keeps every outcome for all groups.

func (*Searcher) Endpoints

func (s *Searcher) Endpoints() (good, bad Probe, err error)

Endpoints tests the good and the bad commit; both must be testable.

func (*Searcher) Outcome

func (s *Searcher) Outcome(i int) (Probe, bool)

Outcome returns what is known of commit i.

func (*Searcher) Probe

func (s *Searcher) Probe(i int) (Probe, error)

Probe returns the outcome of commit i, testing it the first time.

func (*Searcher) Search

func (s *Searcher) Search(group string) (Answer, error)

Search finds the first commit where group drifts. Commits already tested (for another group) narrow the range without a new test; a new test goes to the untested commit nearest the middle, so a commit that cannot be tested is stepped around as git bisect skip does.

func (*Searcher) Skipped

func (s *Searcher) Skipped() []int

Skipped returns the commits that could not be tested, in path order.

func (*Searcher) Tested

func (s *Searcher) Tested() []int

Tested returns the commits tested so far, in the order they were tested.

type Worktree

type Worktree struct {
	Dir string
	// contains filtered or unexported fields
}

Worktree is a detached checkout of the repository in a temporary folder.

func (*Worktree) Checkout

func (w *Worktree) Checkout(ctx context.Context, commit string) error

Checkout puts the worktree on a commit. Files the previous commit's build left that git does not ignore are removed; ignored ones (dependencies, build caches) stay, so a build does not start from nothing every time.

func (*Worktree) Remove

func (w *Worktree) Remove() error

Remove deletes the worktree and its record in the repository. It works with a context of its own, so it also runs after an interrupt.

Jump to

Keyboard shortcuts

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