grit_lib/error.rs
1//! Shared error types for the Gust library.
2//!
3//! Library code uses [`Error`] (a `thiserror` enum) so callers can match on
4//! specific failure modes. The binary wraps these with `anyhow` for human-
5//! readable top-level reporting.
6
7use thiserror::Error;
8
9/// The top-level error type for all Gust library operations.
10#[derive(Debug, Error)]
11#[non_exhaustive]
12pub enum Error {
13 /// A repository could not be found or is structurally invalid.
14 #[error("not a git repository (or any of the parent directories): {0}")]
15 NotARepository(String),
16
17 /// A bare repository was found but access is forbidden by safe.bareRepository.
18 #[error("cannot use bare repository '{0}' (safe.bareRepository is 'explicit')")]
19 ForbiddenBareRepository(String),
20
21 /// The repository is owned by a different user (safe.directory).
22 #[error("detected dubious ownership in repository at '{0}'")]
23 DubiousOwnership(String),
24
25 /// Repository format version is not supported by this implementation.
26 #[error("unsupported repository format version '{0}'")]
27 UnsupportedRepositoryFormatVersion(u32),
28
29 /// Repository declares an unsupported extension.
30 #[error("unknown repository extension '{0}'")]
31 UnsupportedRepositoryExtension(String),
32
33 /// A supplied object ID string was not valid hex or the wrong length.
34 #[error("invalid object id '{0}'")]
35 InvalidObjectId(String),
36
37 /// The requested object does not exist in the object store.
38 #[error("object not found: {0}")]
39 ObjectNotFound(String),
40
41 /// An object's stored data is corrupt or malformed.
42 #[error("corrupt object: {0}")]
43 CorruptObject(String),
44
45 /// An unsupported or unknown object type was encountered.
46 #[error("unknown object type '{0}'")]
47 UnknownObjectType(String),
48
49 /// Loose object header type field exceeds Git's 32-byte limit.
50 #[error("header for {oid} too long, exceeds 32 bytes")]
51 ObjectHeaderTooLong { oid: String },
52
53 /// An I/O error from the underlying filesystem.
54 #[error("I/O error: {0}")]
55 Io(#[from] std::io::Error),
56
57 /// A zlib compression or decompression failure.
58 #[error("zlib error: {0}")]
59 Zlib(String),
60
61 /// Loose object bytes hash to a different OID than the file path implies (`git fsck` / `read_loose_object`).
62 #[error("{real_oid}: hash-path mismatch, found at: {path}")]
63 LooseHashMismatch {
64 /// Repository-relative or filesystem path to the loose object file.
65 path: String,
66 /// Hex object id of the unpacked contents.
67 real_oid: String,
68 },
69
70 /// The index file is missing, truncated, or has a bad header.
71 #[error("index error: {0}")]
72 IndexError(String),
73
74 /// The cache-tree extension references more entries than the index contains. Git emits this
75 /// (verbatim, prefixed with `error: `) when a tree with duplicate path entries is read into the
76 /// index (`t4058-diff-duplicates`).
77 #[error("corrupted cache-tree has entries not present in index")]
78 CacheTreeCorrupt,
79
80 /// A reference name or value is invalid.
81 #[error("invalid ref: {0}")]
82 InvalidRef(String),
83
84 /// A general path-related error (invalid UTF-8, out-of-bounds, etc.).
85 #[error("path error: {0}")]
86 PathError(String),
87
88 /// A configuration file parsing or access error.
89 #[error("config error: {0}")]
90 ConfigError(String),
91
92 /// A commit/tag signing or signature-verification error.
93 #[error("{0}")]
94 Signing(String),
95
96 /// HTTP authentication failed: the server required credentials (`401`) and
97 /// either no credential provider was wired, the provider could not supply a
98 /// usable username/password, the server demanded an unsupported auth scheme,
99 /// or the supplied credentials were rejected.
100 ///
101 /// Distinct from [`Error::Message`] so embedders can detect an authentication
102 /// failure (and e.g. fall back to an interactive/subprocess path) rather than
103 /// string-matching, and so the failure surfaces typed instead of hanging.
104 #[error("authentication failed: {0}")]
105 Auth(String),
106
107 /// A push carried `--push-option` values but the remote `git-receive-pack`
108 /// did not advertise the `push-options` capability, so the options cannot be
109 /// transmitted.
110 ///
111 /// Distinct from [`Error::Message`] so embedders can detect this specific
112 /// negotiation failure (and e.g. fall back to a subprocess push) rather than
113 /// string-matching. The message matches Git's
114 /// `fatal: the receiving end does not support push options`.
115 #[error("the receiving end does not support push options")]
116 PushOptionsUnsupported,
117
118 /// User-facing message that should be printed verbatim (no extra prefix).
119 ///
120 /// Used for revision errors that must match Git's `fatal:` lines exactly.
121 #[error("{0}")]
122 Message(String),
123}
124
125/// Convenience alias for `Result<T, Error>`.
126pub type Result<T> = std::result::Result<T, Error>;