Returns the primary clone's root for the repo containing dir, or nil
when dir is not inside a git work tree. For a linked worktree this is
the root of the clone the worktree was created from (via git rev-parse --git-common-dir); for a primary checkout it is the repo root itself.
Project resolution uses this to map a worktree directory back to the
configured project root.
GitCli behaviour (fnord v0.9.38)
View SourceFacade for direct git CLI calls.
Covers repo classification (is_git_repo?/0, worktree_root/0),
branch reporting (current_branch/0, default_branch/1), tree
enumeration for indexing (ls_tree/2, show_blob/3), gitignore
resolution (ignored_files/1), and formatted user-facing messages
(git_info/0).
Note: default_branch/1 resolves the project's indexing branch
with a strict fallback chain (origin/HEAD → main → master → nil).
For the looser worktree-root resolution that falls back to the
current branch, see GitCli.Worktree.default_base_branch/1.
This module is the git-subprocess boundary: every public function
dispatches through impl/0, resolved via the :git_cli Globals key
and defaulting to GitCli.Default (the real System.cmd wrapper).
Unlike the lower transport seams, tests do NOT point this key at a
mock by default - the real implementation stays in place, and tests
that need to script git state opt in per test (see
Fnord.TestCase.mock_git_cli/0). GitCli.Default routes its own
calls to public siblings back through this facade so a test double
intercepts nested calls, not just top-level entry points.
Summary
Types
Parsed metadata for a single commit, as reported by git show.
committed_at is the raw unix-epoch string git emits for %at.
Parsed git show --numstat output: the list of changed paths and the
per-file addition/deletion counts. Binary files report 0/0.
Functions
Returns parsed metadata for a single commit. Errors on unparseable
output - the most common cause is a literal \x1f byte in a subject
or body, which collides with the field separator used in the format
string.
Returns the changed file list and per-file diffstat counts for a single commit.
Lists every commit SHA reachable from ref, newest first (rev-list
order). Used by the commit indexer to enumerate index candidates.
Returns the current branch name for the effective directory, the
short SHA prefixed with @ when HEAD is detached, or nil on failure.
Returns the repository's default branch for indexing purposes
Returns git diff --stat output for range at root.
Fetches ref from remote at root. Network-touching: review uses it
to make never-checked-out branches reviewable, and nothing else should
reach for it casually.
Returns a formatted, user-facing description of the current git context (branch and root), or a note that the project is not under version control.
Returns a map of absolute paths to true for every gitignored file
under root. Returns an empty map if root is nil.
Returns true when the effective directory (project root override or cwd) is inside a git working tree.
Returns true when the given path is inside a git working tree.
Returns true when the effective directory is inside a git working tree. We currently treat any such directory as worktree-aware enough for callers using this predicate, including detached HEAD state.
Returns git log --oneline output for range at root.
Lists every blob in branch's tree as {blob_sha, rel_path} pairs.
The blob sha is git's content-addressed hash and is stable across
clones and checkouts, so it's usable as a freshness key for the
indexer.
Returns the merge base of two refs at root. The review ops below
return bare :error on git failure rather than {:error, term}:
their callers present target-specific context ("failed to resolve
branch X") and have no use for raw plumbing output.
Returns the primary clone's root for the repo containing dir, or nil
when dir is not inside a git work tree. For a linked worktree this is
the root of the clone the worktree was created from (via git rev-parse --git-common-dir); for a primary checkout it is the repo root itself.
Project resolution uses this to map a worktree directory back to the
configured project root.
Returns the repository toplevel for the effective directory, or nil when not in a repo (or git is not installed).
Returns the repository toplevel for the given directory, or
{:error, :not_a_repo} when the path is not inside a git working
tree. Unlike repo_root/0, this ignores the project root override -
callers use it to resolve the repo that owns an explicit path (e.g. a
stored worktree) regardless of session state.
Returns the content of rel_path as it exists on branch, or an
error tuple if git rejects the request (missing file, invalid branch,
etc.). Content is returned as a binary; binaries that aren't valid
UTF-8 are still returned — callers decide how to handle them.
Returns the raw git status --short --untracked-files=all lines for the
repo at root, one entry per changed or untracked file. Used by
validation-rule changed-file discovery.
Resolves ref to a commit SHA if it exists locally (rev-parse --verify --quiet ref^{commit}). Never touches the network; pair with
fetch_ref/3 to make remote-only refs resolvable via FETCH_HEAD.
Returns the toplevel of the current worktree, or nil when not in one.
Types
@type commit_meta() :: %{ sha: String.t(), parent_shas: [String.t()], author: String.t(), committed_at: String.t(), subject: String.t(), body: String.t() }
Parsed metadata for a single commit, as reported by git show.
committed_at is the raw unix-epoch string git emits for %at.
@type commit_numstat() :: {[String.t()], [ %{ file: String.t(), additions: non_neg_integer(), deletions: non_neg_integer() } ]}
Parsed git show --numstat output: the list of changed paths and the
per-file addition/deletion counts. Binary files report 0/0.
Callbacks
@callback commit_meta(String.t(), String.t()) :: {:ok, commit_meta()} | {:error, term()}
@callback commit_numstat(String.t(), String.t()) :: {:ok, commit_numstat()} | {:error, term()}
@callback current_branch() :: String.t() | nil
@callback git_info() :: String.t()
@callback is_git_repo?() :: boolean()
@callback is_worktree?() :: boolean()
@callback repo_root() :: String.t() | nil
@callback worktree_root() :: String.t() | nil
Functions
@spec commit_meta(String.t(), String.t()) :: {:ok, commit_meta()} | {:error, term()}
Returns parsed metadata for a single commit. Errors on unparseable
output - the most common cause is a literal \x1f byte in a subject
or body, which collides with the field separator used in the format
string.
@spec commit_numstat(String.t(), String.t()) :: {:ok, commit_numstat()} | {:error, term()}
Returns the changed file list and per-file diffstat counts for a single commit.
Lists every commit SHA reachable from ref, newest first (rev-list
order). Used by the commit indexer to enumerate index candidates.
@spec current_branch() :: String.t() | nil
Returns the current branch name for the effective directory, the
short SHA prefixed with @ when HEAD is detached, or nil on failure.
Returns the repository's default branch for indexing purposes:
origin/HEAD- the remote's declared default (usually main).- Local
mainormaster, in that order. nil- do not silently fall back to the current branch, since that would makefnord indexon a feature branch index the feature branch rather than the project's canonical source.
Callers fall back to filesystem-mode indexing when this returns nil, so the user still gets their working tree indexed; they just won't get default-branch semantics.
Returns git diff --stat output for range at root.
Fetches ref from remote at root. Network-touching: review uses it
to make never-checked-out branches reviewable, and nothing else should
reach for it casually.
@spec git_info() :: String.t()
Returns a formatted, user-facing description of the current git context (branch and root), or a note that the project is not under version control.
Returns a map of absolute paths to true for every gitignored file
under root. Returns an empty map if root is nil.
@spec impl() :: module()
@spec is_git_repo?() :: boolean()
Returns true when the effective directory (project root override or cwd) is inside a git working tree.
Returns true when the given path is inside a git working tree.
@spec is_worktree?() :: boolean()
Returns true when the effective directory is inside a git working tree. We currently treat any such directory as worktree-aware enough for callers using this predicate, including detached HEAD state.
Returns git log --oneline output for range at root.
Lists every blob in branch's tree as {blob_sha, rel_path} pairs.
The blob sha is git's content-addressed hash and is stable across
clones and checkouts, so it's usable as a freshness key for the
indexer.
Returns the merge base of two refs at root. The review ops below
return bare :error on git failure rather than {:error, term}:
their callers present target-specific context ("failed to resolve
branch X") and have no use for raw plumbing output.
@spec repo_root() :: String.t() | nil
Returns the repository toplevel for the effective directory, or nil when not in a repo (or git is not installed).
Returns the repository toplevel for the given directory, or
{:error, :not_a_repo} when the path is not inside a git working
tree. Unlike repo_root/0, this ignores the project root override -
callers use it to resolve the repo that owns an explicit path (e.g. a
stored worktree) regardless of session state.
Returns the content of rel_path as it exists on branch, or an
error tuple if git rejects the request (missing file, invalid branch,
etc.). Content is returned as a binary; binaries that aren't valid
UTF-8 are still returned — callers decide how to handle them.
Returns the raw git status --short --untracked-files=all lines for the
repo at root, one entry per changed or untracked file. Used by
validation-rule changed-file discovery.
Resolves ref to a commit SHA if it exists locally (rev-parse --verify --quiet ref^{commit}). Never touches the network; pair with
fetch_ref/3 to make remote-only refs resolvable via FETCH_HEAD.
@spec worktree_root() :: String.t() | nil
Returns the toplevel of the current worktree, or nil when not in one.