RepoError variants¶
Every Repo method returns Result<_, RepoError>. The enum is
#[non_exhaustive], so match with a _ arm.
What can I match on?¶
The variant shape is the public contract. The cause string is not: it
carries whatever gix or git stderr said, and it changes when the backend
changes. Assert on matches!(err, RepoError::OpenFailed { .. }), never on the
text.
RepoError does not implement Clone, unlike ProviderError. It holds a
live std::io::Error in the Io variant and a CredentialError in Auth.
Which method produces which variant?¶
| Variant | Produced by |
|---|---|
Io |
reserved; no method in the crate constructs it today |
OpenFailed |
open |
InitFailed |
init |
CloneFailed |
clone |
FetchFailed |
fetch |
CheckoutFailed |
checkout |
CommitFailed |
commit |
StatusFailed |
status |
WalkFailed |
walk, and blame |
DiffFailed |
diff |
PushFailed |
push |
RevspecNotFound |
walk, diff, blame, checkout |
DirtyWorkingTree |
checkout |
Auth |
clone, fetch, push |
PushUnsupported |
never |
OpenFailed / InitFailed¶
Codes rtb_forge::git::open_failed and rtb_forge::git::init_failed. path is
the path you passed. cause is gix's stringified error, or a
spawn_blocking join error: … string if the background task itself failed.
OpenFailed is what you get for a directory that is not a repository, and for
a repository whose .git cannot be read.
CloneFailed¶
Code rtb_forge::git::clone_failed. The cause prefix tells you how far it
got:
| Prefix | Stage |
|---|---|
prepare: … |
gix could not parse the URL or prepare the destination |
fetch: … |
gix refs negotiation or object download failed |
checkout: … |
gix could not write the working tree |
spawn \git clone`: …| thegit` binary could not be launched (authenticated clones only) |
|
git clone: … |
git clone exited non-zero; the rest is its stderr |
open post-clone: … |
the clone succeeded but the result could not be opened |
FetchFailed / PushFailed¶
Codes rtb_forge::git::fetch_failed and rtb_forge::git::push_failed. cause
is either spawn \git …`: orgit …:
PushFailed's API documentation claims the variant is "only reachable when the
git2-fallback Cargo feature is enabled". That is stale: there is no such
feature, and this is the ordinary failure variant for Repo::push.
When a spawn_blocking join fails, remote and refspec are the empty
string rather than the values you passed — the owned copies were moved into
the failed task. Do not rely on those fields being populated in every case.
CheckoutFailed¶
Code rtb_forge::git::checkout_failed. Reached when git checkout exits
non-zero for a reason that does not look like a missing revspec — see
RevspecNotFound below for how that call is made.
CommitFailed¶
Code rtb_forge::git::commit_failed. There is no path or message field;
everything is in cause:
cause |
Meaning |
|---|---|
no paths supplied — commit requires at least one path to stage |
you passed an empty slice |
spawn \git add`: …| thegit` binary is missing or not executable |
|
git add: … |
git add rejected a path |
git commit: … |
nothing staged, no configured identity, a hook refused, … |
git rev-parse: … |
the commit was created but its OID could not be read |
oid utf-8: … |
git rev-parse produced non-UTF-8 output |
Note the ordering: a git rev-parse failure means the commit did happen.
Do not treat CommitFailed as proof the repository is unchanged.
StatusFailed / WalkFailed / DiffFailed¶
Codes rtb_forge::git::status_failed, rtb_forge::git::walk_failed,
rtb_forge::git::diff_failed.
WalkFailed covers more than its name suggests. It is produced by:
walkfor an unsupported revspec kind —unsupported revspec kind: ….walkfor object-store failures partway through, delivered as anErritem on the stream rather than from thewalk()call itself.blamefor every failure that is not a missing revspec — resource-cache setup, commit lookup, gix-blame internals. There is noBlameFailedvariant.
RevspecNotFound¶
Code rtb_forge::git::revspec_not_found. Produced by walk, diff, blame
and checkout.
The revspec field is not always a bare revspec:
- From
blame, a missing file is reported asRevspecNotFoundwith arevspecof the form<file path> at <revspec>. There is no separate file-not-found variant, so you cannot distinguish "bad revision" from "file absent at that revision" by variant alone. - From
checkout, the classification comes from matchinggit's stderr againstdid not match any,unknown revision,not a valid object nameandpathspec. Under a non-English locale those phrases do not appear and the same situation arrives asCheckoutFailedinstead.
DirtyWorkingTree¶
Code rtb_forge::git::dirty_working_tree. Carries paths: Vec<PathBuf> — the
staged bucket first, then the unstaged one.
Only checkout with force = false produces it. Because
RepoStatus::staged is always empty,
the staged half contributes nothing and the list is effectively the unstaged
paths.
Auth¶
Code rtb_forge::git::auth. Wraps rtb_credentials::CredentialError as a
#[source], so the underlying reason — env var unset, keychain locked, literal
refused under CI=true — is available through std::error::Error::source.
This variant means the credential could not be resolved locally. It does
not mean the remote rejected it: a token the server refuses produces
CloneFailed / FetchFailed / PushFailed carrying git's stderr.
PushUnsupported¶
Code rtb_forge::git::push_unsupported, with help text suggesting you enable
git2-fallback.
Nothing constructs this variant. It is a leftover from a design where push
would have needed libgit2. Push works on any build with the git feature, and
there is no git2-fallback feature to enable. The variant remains only because
removing it from a #[non_exhaustive] public enum would be a breaking change.
If you are handling it in a match arm, that arm is dead code.