Documentation
¶
Overview ¶
Package gitcli wraps the system git binary: clone, log --numstat --name-status, and per-path log.
Index ¶
- type Client
- func (c *Client) CatFileBatch(ctx context.Context, clonePath string, refs []string, ...) error
- func (c *Client) CheckAncestors(ctx context.Context, clonePath string, candidates []string, descendant string) (map[string]bool, error)
- func (c *Client) CheckMailmap(ctx context.Context, clonePath, name, email string) (string, string, error)
- func (c *Client) Clone(ctx context.Context, slug, dest string, shallowSince time.Time) error
- func (c *Client) DefaultBranch(ctx context.Context, clonePath string) (string, error)
- func (c *Client) HeadAndDefaultBranch(ctx context.Context, clonePath string) (string, string, error)
- func (c *Client) HeadSHA(ctx context.Context, clonePath string) (string, error)
- func (c *Client) IsAncestor(ctx context.Context, clonePath, ancestor, descendant string) (bool, error)
- func (c *Client) LogNumstat(ctx context.Context, clonePath string, since, until time.Time, branch string) ([]CommitRecord, error)
- func (c *Client) LogPath(ctx context.Context, clonePath, path string) (string, time.Time, time.Time, error)
- func (c *Client) LsFiles(ctx context.Context, clonePath string) ([]string, error)
- func (c *Client) LsRemote(ctx context.Context, slug string) error
- func (c *Client) ReadMailmap(_ context.Context, clonePath string) (*Mailmap, error)
- func (c *Client) RemoteBranches(ctx context.Context, clonePath string) ([]RemoteBranch, error)
- func (c *Client) ShowFile(ctx context.Context, clonePath, sha, path string) ([]byte, error)
- type CommitRecord
- type FileChange
- type Mailmap
- type RemoteBranch
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
Client is a thin wrapper around the system git binary. If GitHubToken is set, Clone and LsRemote authenticate to github.com using that token via an inline credential helper: the token value is passed in the subprocess env as XRAY_GIT_TOKEN and read by the helper at credential-fill time, never appearing in argv or in xray's debug log. Other methods operate on a local clone and do not consult the token. When GitHubToken is empty the client degrades to ambient git auth (SSH, credential helper, gh CLI, etc.) — the historical behaviour.
func (*Client) CatFileBatch ¶
func (c *Client) CatFileBatch(ctx context.Context, clonePath string, refs []string, fn func(ref string, content []byte)) error
CatFileBatch calls git cat-file --batch for all refs (each "<sha>:<path>") and invokes fn once per ref in input order. fn receives the raw blob content, or nil when the object is absent or not a blob. Content per object is capped at maxShowFileBytes. One subprocess handles all refs.
func (*Client) CheckAncestors ¶
func (c *Client) CheckAncestors(ctx context.Context, clonePath string, candidates []string, descendant string) (map[string]bool, error)
CheckAncestors reports for each candidate OID whether it is an ancestor of (or equal to) descendant. One `git log` call replaces N separate `git merge-base --is-ancestor` subprocess spawns — the key saving for repos with many single-parent-merge PRs (ADR-021 rebase/squash detection).
`git log --pretty=%H <cand1> <cand2> ... ^<descendant>` outputs every commit reachable from any candidate but NOT from descendant. A candidate that appears in the output is therefore NOT an ancestor of descendant; one that is absent IS an ancestor (all its reachable commits are already reachable from descendant).
func (*Client) CheckMailmap ¶
func (c *Client) CheckMailmap(ctx context.Context, clonePath, name, email string) (string, string, error)
CheckMailmap shells to `git check-mailmap` to resolve a single identity. Used by the test fixture to validate parser output against git itself; not called on the production hot path because parsing per repo and resolving in memory is orders of magnitude cheaper than forking per commit.
func (*Client) Clone ¶
Clone shallow-clones slug ("owner/repo") into dest. dest must not exist. The shallow window starts at shallowSince - 30d to keep rename history (commit_files prev_path tracking) coherent at the window boundary.
func (*Client) DefaultBranch ¶
DefaultBranch resolves the default branch of clonePath from origin/HEAD's symbolic ref. Falls back to "main" on failure.
func (*Client) HeadAndDefaultBranch ¶ added in v0.4.9
func (c *Client) HeadAndDefaultBranch(ctx context.Context, clonePath string) (string, string, error)
HeadAndDefaultBranch resolves HEAD's SHA and the default branch in a single `git` subprocess, replacing the sequential HeadSHA + DefaultBranch pair on the clone path. At N repos the saved fork+exec on macOS (~5ms each, ~250ms at 50 repos) compounds noticeably.
`git rev-parse HEAD --symbolic-full-name refs/remotes/origin/HEAD` prints two stdout lines:
- line 1: HEAD's SHA (always, on any normal repo).
- line 2: either `refs/remotes/origin/<branch>` (origin/HEAD set, exit 0) or the literal `refs/remotes/origin/HEAD` (unresolved, exit 128).
On the failure path stdout is still well-formed, so we parse it regardless of exit status and surface a real error only when line 1 isn't a valid SHA. The default-branch lookup retains the same "fall back to main" semantics as DefaultBranch.
func (*Client) IsAncestor ¶
func (c *Client) IsAncestor(ctx context.Context, clonePath, ancestor, descendant string) (bool, error)
IsAncestor reports whether `ancestor` is an ancestor of (or equal to) `descendant` in clonePath. Implemented via `git merge-base --is-ancestor`, which exits 0 when true and 1 when false; any other exit code is surfaced as an error. Added to support ADR-021's merge-method derivation in the github connector: rebase vs squash is the reachability of the PR's head commits from the merge commit.
func (*Client) LogNumstat ¶
func (c *Client) LogNumstat(ctx context.Context, clonePath string, since, until time.Time, branch string) ([]CommitRecord, error)
LogNumstat streams parsed commits + per-file numstat in the window. branch is the ref to walk; if empty, HEAD is used.
func (*Client) LogPath ¶
func (c *Client) LogPath(ctx context.Context, clonePath, path string) (string, time.Time, time.Time, error)
LogPath returns the first-seen commit/time and last-modified time for a single path. The clone must contain enough history to reach the path's introducing commit; for working-tree artifacts this is satisfied by the shallowSince - 30d clone window.
func (*Client) LsFiles ¶
LsFiles returns the list of files tracked at HEAD in the cloned repo (git ls-files --cached). Paths are relative to the repo root and use forward slashes. .gitignore is honoured naturally by git's index.
func (*Client) ReadMailmap ¶
ReadMailmap reads the repo's top-level .mailmap (the only location git supports without explicit config), returning ParseMailmap'd state. Missing file returns a zero-value Mailmap with Applied() == false and nil error; any other read or parse error is returned.
func (*Client) RemoteBranches ¶
RemoteBranches enumerates origin's branches from the local clone, returning name, tip SHA, and committer date for each. `origin/HEAD` is filtered out. Replaces a REST ListBranches round-trip; the data is already in the clone after fetch.
type CommitRecord ¶
type CommitRecord struct {
SHA string
AuthorHandle string
AuthorEmail string
CommitterHandle string
CommitterEmail string
AuthoredAt time.Time
CommittedAt time.Time
Subject string
Body string
ParentSHAs []string
Files []FileChange
}
CommitRecord is a parsed git log entry covering everything the github connector needs to populate commits, commit_files, and commit_coauthors. Body is exposed so the connector can parse trailers and structured signals; the connector discards it afterwards.
type FileChange ¶
type FileChange struct {
Path string
PrevPath string
ChangeType string // A | M | D | R | C
Additions int
Deletions int
}
FileChange is a single per-file numstat row attached to a commit.
type Mailmap ¶
type Mailmap struct {
// contains filtered or unexported fields
}
Mailmap resolves alias (name, email) pairs to canonical (name, email). It mirrors git's resolution semantics as implemented by `git check-mailmap`: the four supported line shapes are
Proper Name <commit@email.xx> <proper@email.xx> <commit@email.xx> Proper Name <proper@email.xx> <commit@email.xx> Proper Name <proper@email.xx> Commit Name <commit@email.xx>
Comment ('#') and blank lines are skipped. Lookup keys are the (name, email) pair from the commit side; entries that didn't supply a commit-name match any commit-name with the same commit-email.
A zero-value Mailmap returns inputs unchanged from Resolve and reports Applied() == false — the run.go aggregator uses Applied() to populate manifest.mailmap_applied.
func ParseMailmap ¶
ParseMailmap parses raw .mailmap bytes into a Mailmap. A zero-entry file (only comments / blanks) returns an empty, non-applied Mailmap.