gitclient

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: MPL-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package gitclient is a small exec-based Git client used by the filter, diff/merge drivers, the pre-push hook, and setup/upgrade. It never links a Git library: every call shells out to the installed `git`, runs with an explicit environment, captures stderr, and returns typed errors so callers can distinguish "git failed" from "git is missing" from "context cancelled".

The client is deliberately narrow: it exposes only the plumbing FXVCS needs and never runs a porcelain command that could prompt, page, or open an editor.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrGitNotFound is returned when the git executable cannot be located.
	ErrGitNotFound = errors.New("gitclient: git executable not found")
	// ErrNotRepository is returned when a command runs outside a Git repository.
	ErrNotRepository = errors.New("gitclient: not a git repository")
)

Errors.

View Source
var DefaultRetry = Retry{Attempts: 5, Backoff: 100 * time.Millisecond}

DefaultRetry waits out an ordinary collision — roughly 1.5s across five attempts — without turning a genuinely stuck lock into a long stall.

View Source
var ErrLockContention = errors.New("gitclient: git index or ref lock is held by another process")

ErrLockContention is the transient class: another process held Git's index or a ref lock for the moment we asked.

FXVCS has no daemon. The CLI, the desktop application, the editor's Git integration and whatever else the operator runs all drive `git` against one worktree at the same time, so a collision on $GIT_DIR/index.lock is an ordinary event on a healthy machine rather than a failure worth reporting. The holder releases it in milliseconds; waiting is the whole remedy.

Functions

func BatchPaths

func BatchPaths(paths []string, callEmpty bool, fn func(batch []string) error) error

BatchPaths splits paths into command-line-sized batches and calls fn once per batch, in order. An empty list calls fn once with no paths only when callEmpty is set, which is what a "no pathspec means everything" command needs. The first error stops the walk.

func IsLockContention

func IsLockContention(err error) bool

IsLockContention reports whether err is a failed invocation that could succeed on a retry because someone else held a Git lock.

It matches on Git's own message because Git offers nothing better: every one of these exits 128 with a message naming the lock file, and exit codes alone cannot tell "someone else is mid-commit" from "your pathspec is wrong". The match is deliberately narrow — a lock file by name — so that a real failure is never retried into a delay.

Types

type Attrs

type Attrs struct {
	Filter string
	Diff   string
	Merge  string
	Text   string
}

Attrs holds the effective FXVCS-relevant attributes of one path. Each value is one of: the attribute value, "set", "unset", or "unspecified", exactly as git check-attr reports them.

func (Attrs) IsManaged

func (a Attrs) IsManaged() bool

IsManaged reports whether the path is routed through the fxvcs filter.

type Client

type Client struct {
	// Dir is the working directory for every command ("" = process cwd).
	Dir string
	// Env is the complete environment for git. nil inherits the process
	// environment. Tests pass an isolated environment (HOME, GIT_CONFIG_*).
	Env []string
	// Executable overrides the git binary ("" = "git" from PATH).
	Executable string
}

Client runs git in a fixed directory with a fixed environment.

func New

func New(dir string) *Client

New returns a client rooted at dir inheriting the process environment.

func (*Client) Available

func (c *Client) Available() bool

Available reports whether the git executable can be found.

func (*Client) CatFileBlob

func (c *Client) CatFileBlob(ctx context.Context, name string) ([]byte, error)

CatFileBlob returns the raw bytes of a blob given any object name (oid, ":path" for the index, "<rev>:path").

func (*Client) CatFileBlobTo

func (c *Client) CatFileBlobTo(ctx context.Context, name string, w io.Writer) error

CatFileBlobTo streams a blob to w.

func (*Client) CheckAttr

func (c *Client) CheckAttr(ctx context.Context, path string) (Attrs, error)

CheckAttr returns filter/diff/merge/text attributes for a repo-relative path.

func (*Client) CheckAttrs

func (c *Client) CheckAttrs(ctx context.Context, paths []string) (map[string]Attrs, error)

CheckAttrs is CheckAttr for many paths (one git process, -z --stdin).

func (*Client) ConfigGet

func (c *Client) ConfigGet(ctx context.Context, key string) (value string, ok bool, err error)

ConfigGet reads a key using git's normal precedence. ok is false when unset.

func (*Client) ConfigSet

func (c *Client) ConfigSet(ctx context.Context, key, value string) error

ConfigSet sets a repository-local (--local) key.

func (*Client) ConfigUnset

func (c *Client) ConfigUnset(ctx context.Context, key string) error

ConfigUnset removes a repository-local key (no error if absent).

func (*Client) DiffTreePaths

func (c *Client) DiffTreePaths(ctx context.Context, commit string) ([]string, error)

DiffTreePaths returns the paths added or modified by commit relative to its first parent (or everything for a root commit).

func (*Client) GitCommonDir

func (c *Client) GitCommonDir(ctx context.Context) (string, error)

GitCommonDir returns $GIT_COMMON_DIR (absolute; equals GitDir outside linked worktrees).

func (*Client) GitDir

func (c *Client) GitDir(ctx context.Context) (string, error)

GitDir returns $GIT_DIR (absolute).

func (*Client) GitPath

func (c *Client) GitPath(ctx context.Context, name string) (string, error)

GitPath resolves `git rev-parse --git-path <name>` (e.g. "fxvcs", "hooks", "info/exclude") to an absolute path, honoring worktrees and core.hooksPath.

func (*Client) HashObject

func (c *Client) HashObject(ctx context.Context, r io.Reader, write bool) (string, error)

HashObject returns the Git blob id of r; write=true also stores it.

func (*Client) Locations

func (c *Client) Locations(ctx context.Context) (top, gitDir, commonDir string, err error)

Locations resolves the working-tree root, $GIT_DIR and $GIT_COMMON_DIR in a single invocation.

It exists because opening a repository needed all three and asked for them one at a time. Every Git question costs a process, and on an interactive caller that opens a repository per request those three spawns are paid before any work begins — on macOS and Windows that is most of what a small query costs. rev-parse answers all three in argument order for the price of one.

func (*Client) LsFilesStage

func (c *Client) LsFilesStage(ctx context.Context, path string) ([]StageEntry, error)

LsFilesStage returns the index entries for a path (0 = merged; 1/2/3 during a conflict). ok is false when the path is not in the index.

func (*Client) RevList

func (c *Client) RevList(ctx context.Context, args ...string) ([]string, error)

RevList returns commit ids for the given rev-list arguments.

func (*Client) RevParse

func (c *Client) RevParse(ctx context.Context, arg string) (string, error)

RevParse runs `git rev-parse <arg>` and returns the single-line result.

func (*Client) Run

func (c *Client) Run(ctx context.Context, args ...string) ([]byte, error)

Run executes git with args and returns stdout. Stderr is captured into the returned *Error on failure.

func (*Client) RunBatched

func (c *Client) RunBatched(ctx context.Context, prefix []string, paths []string) ([]byte, error)

RunBatched runs `git <prefix...> <batch...>` once per path batch and concatenates the outputs. Use it for any command whose path list comes from the repository rather than from a fixed set.

func (*Client) RunInput

func (c *Client) RunInput(ctx context.Context, stdin io.Reader, args ...string) ([]byte, error)

RunInput is Run with stdin.

func (*Client) RunRetry

func (c *Client) RunRetry(ctx context.Context, rt Retry, args ...string) ([]byte, error)

RunRetry is Run for a command that may be run again unchanged, retrying while another process holds the Git index or a ref lock.

Only idempotent commands may use it: it cannot tell a command that did nothing from one that did its work and then failed to write the index.

func (*Client) RunStreams

func (c *Client) RunStreams(ctx context.Context, stdin io.Reader, stdout io.Writer, args ...string) error

RunStreams executes git streaming stdout to w (bounded memory for large blobs). Stderr is always captured.

func (*Client) RunString

func (c *Client) RunString(ctx context.Context, args ...string) (string, error)

RunString is Run returning trimmed stdout as a string.

func (*Client) TopLevel

func (c *Client) TopLevel(ctx context.Context) (string, error)

TopLevel returns the absolute working-tree root.

func (*Client) Version

func (c *Client) Version(ctx context.Context) (string, error)

Version returns the `git version` string.

func (*Client) WithDir

func (c *Client) WithDir(dir string) *Client

WithDir returns a copy of the client rooted at dir.

func (*Client) WithEnv

func (c *Client) WithEnv(env []string) *Client

WithEnv returns a copy of the client using env as the complete environment.

type Error

type Error struct {
	Args     []string
	ExitCode int
	Stderr   string
	Err      error
}

Error is a failed git invocation. Stderr is captured verbatim (trimmed) so callers can surface Git's own message.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type Retry

type Retry struct {
	// Attempts is the total number of invocations (0 or 1 = no retry).
	Attempts int
	// Backoff is the wait before the second attempt; it doubles thereafter.
	Backoff time.Duration
}

Retry bounds a wait for a busy Git lock.

type StageEntry

type StageEntry struct {
	Mode  string
	OID   string
	Stage int
	Path  string
}

StageEntry is one `ls-files --stage` row.

Directories

Path Synopsis
Package gittest creates throwaway Git repositories for tests.
Package gittest creates throwaway Git repositories for tests.

Jump to

Keyboard shortcuts

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