gitcli

package
v0.172.7 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package gitcli is task-8's real git-operation adapter: it builds argv, runs it through internal/runner, and parses the output, so a consumer package's own narrow ports.go (as internal/streams/ports.go, internal/streamsync/ports.go and internal/locallink/ports.go already declare) can be backed by real git without depending on os/exec at all.

wb runs the `git` executable and imports no Go git library (the root README's "Why WB runs the `git` CLI" section); this package is where that choice lives.

This is the plan's PR-1 adapter skeleton: a handful of read-only operations, chosen because they are easy to contract-test against both real git and a fake (internal/gitcli/gitclitest), proving the pattern before any consumer package migrates onto it. It is not meant to be imported by a consumer directly; a consumer's own ports.go declares only the operations it needs, and its adapter can be built the same way this one is, or can embed/delegate to a Client where the operations overlap.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	Runner runner.Runner
}

Client implements Git over a runner.Runner. Its unit tests run against runnertest.Fake; its contract tests (internal/gitcli/contract_test.go, //go:build e2e) run the same cases against real git.

func New

func New(r runner.Runner) Client

New returns a Client backed by r.

func (Client) BranchSetUpstreamTo

func (c Client) BranchSetUpstreamTo(ctx context.Context, dir, upstream, branch string) error

BranchSetUpstreamTo points branch's upstream at upstream.

func (Client) BranchShowCurrent

func (c Client) BranchShowCurrent(ctx context.Context, dir string) (string, error)

BranchShowCurrent reports dir's checked-out branch, empty when HEAD is detached -- unlike CurrentBranch, which resolves detached HEAD to "HEAD" itself; the two are deliberately different git invocations for two different questions, so this is its own method rather than a reuse of CurrentBranch's argv.

func (Client) CherryPick

func (c Client) CherryPick(ctx context.Context, dir, sha string) error

CherryPick replays sha onto the current commit and commits it.

func (Client) CherryPickNoCommit

func (c Client) CherryPickNoCommit(ctx context.Context, dir string, shas ...string) error

CherryPickNoCommit replays shas onto the current commit without writing a commit, leaving the result staged.

func (Client) CommitNoVerify

func (c Client) CommitNoVerify(ctx context.Context, dir, message string) error

CommitNoVerify writes a commit from the current staged state without running hooks.

func (Client) CommitObjectExists

func (c Client) CommitObjectExists(ctx context.Context, dir, sha string) (bool, error)

CommitObjectExists reports whether sha's commit object already exists in dir's object database. Unlike ConfigRegexpMatches and IsAncestor above, it cannot lean on one fixed "exit code 1 means no" shape: `cat-file -e <sha>^{commit}` exits 1 for an object that exists but is not (yet) a commit, and exits 128 with a "fatal: Not a valid object name" message for a sha that is not any object at all -- both are ordinary, error-free negative answers. What must never be read as one is github.com/sneat-dev/wb/internal/runner.ErrRealProcessBlocked: once this method is reached through a guarded runner (as it is once a consumer package migrates onto it), that sentinel means task-24's runtime guard refused to start the process at all, which is a real error the caller must not treat as "the commit doesn't exist". Collapsing every failure into false was the shape this replaced before spec/plans/coverage-to-100 task-17 routed it through a guarded runner: internal/orchestrate's pre-migration commitExistsLocally called an unguarded exec.CommandContext directly, so ErrRealProcessBlocked could never occur there. It can here, so this method (and commitExistsLocally, its only caller) must tell it apart from every other failure, which stays a negative answer exactly as before.

func (Client) ConfigRegexpMatches

func (c Client) ConfigRegexpMatches(ctx context.Context, dir, pattern string) (bool, error)

ConfigRegexpMatches reports whether `git config --get-regexp pattern` in dir finds at least one entry: true with a zero exit status, false with exit status 1 and empty output (git's own "no matches" shape), and an error for anything else.

func (Client) CurrentBranch

func (c Client) CurrentBranch(ctx context.Context, dir string) (string, error)

CurrentBranch reports the checked-out branch of dir.

func (Client) Fetch

func (c Client) Fetch(ctx context.Context, dir, remote string) error

Fetch refreshes remote in dir.

func (Client) FetchRefs

func (c Client) FetchRefs(ctx context.Context, dir, remote string, refs ...string) error

FetchRefs refreshes remote in dir for exactly refs, without --quiet.

func (Client) IsAncestor

func (c Client) IsAncestor(ctx context.Context, dir, ancestor, descendant string) (bool, error)

IsAncestor reports whether ancestor is reachable from descendant in dir.

func (Client) MergeBaseIsAncestorStrict

func (c Client) MergeBaseIsAncestorStrict(ctx context.Context, dir, ancestor, descendant string) error

MergeBaseIsAncestorStrict reports an error whenever `git merge-base --is-ancestor ancestor descendant` exits non-zero, including the ordinary "not an ancestor" exit status 1 -- unlike IsAncestor, which turns that specific exit status into (false, nil). A caller that only wants "did this fail" (never inspecting a bool result) needs that distinction preserved, so this is a second, deliberately stricter method rather than a reuse of IsAncestor.

func (Client) MergeTreeWriteTree

func (c Client) MergeTreeWriteTree(ctx context.Context, dir, a, b string) (string, error)

MergeTreeWriteTree performs a real-merge write-tree of a and b without touching the working tree or any ref, and returns the resulting tree id.

func (Client) PushForceWithLeaseHead

func (c Client) PushForceWithLeaseHead(ctx context.Context, dir, ref, leaseSHA string) error

PushForceWithLeaseHead publishes the current commit (HEAD) to ref under a lease on leaseSHA -- the exact push a landing's branch rewrite uses to replace ref only if it still matches what was read before the rewrite started.

func (Client) RemotePushURL

func (c Client) RemotePushURL(ctx context.Context, dir, remote string) (string, error)

RemotePushURL resolves the push URL of remote in dir.

func (Client) RevListReverseRange

func (c Client) RevListReverseRange(ctx context.Context, dir, from, to string) (string, error)

RevListReverseRange lists the commits in the exclusive range from..to, oldest first.

func (Client) RevParse

func (c Client) RevParse(ctx context.Context, dir, rev string) (string, error)

RevParse resolves rev to a commit SHA in dir.

func (Client) ShowTreeFormat

func (c Client) ShowTreeFormat(ctx context.Context, dir, commit string) (string, error)

ShowTreeFormat resolves commit's tree id.

func (Client) StatusPorcelain

func (c Client) StatusPorcelain(ctx context.Context, dir string) (string, error)

StatusPorcelain reports dir's porcelain-v1 status.

func (Client) WorktreeAddDetached

func (c Client) WorktreeAddDetached(ctx context.Context, dir, path, revision string) error

WorktreeAddDetached adds a new worktree at path, checked out detached at revision.

func (Client) WorktreeRemoveForce

func (c Client) WorktreeRemoveForce(ctx context.Context, dir, worktree string) error

WorktreeRemoveForce removes worktree from dir's repository, discarding any modification it holds.

type Git

type Git interface {
	// CurrentBranch reports the checked-out branch of a worktree.
	CurrentBranch(ctx context.Context, dir string) (string, error)
	// RevParse resolves rev to a commit SHA.
	RevParse(ctx context.Context, dir, rev string) (string, error)
	// IsAncestor reports whether ancestor is reachable from descendant.
	IsAncestor(ctx context.Context, dir, ancestor, descendant string) (bool, error)
	// Fetch refreshes remote in dir.
	Fetch(ctx context.Context, dir, remote string) error
}

Git is the narrow git-operation port this package's Client implements.

type GitError

type GitError struct {
	Argv   []string
	Output string
	Stderr string
	Err    error
}

GitError wraps a failed git invocation with the argv and output git printed, so a caller's error message names the command and its failure details.

func (*GitError) Error

func (e *GitError) Error() string

func (*GitError) Unwrap

func (e *GitError) Unwrap() error

Directories

Path Synopsis
Package gitclitest is the in-memory fake for internal/gitcli.Git, so a unit test can substitute it for a real gitcli.Client without touching a real repository.
Package gitclitest is the in-memory fake for internal/gitcli.Git, so a unit test can substitute it for a real gitcli.Client without touching a real repository.

Jump to

Keyboard shortcuts

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