grit_lib/refs/store/
error.rs1use std::fmt;
4use std::sync::Arc;
5
6use crate::git_dir::GitDirPathOperation;
7use crate::refs::RefnameUnavailable;
8
9use super::{Expected, RawRef};
10
11#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
13#[non_exhaustive]
14pub enum RefStoreError {
15 #[error("cannot lock ref '{name}': lock held")]
17 LockHeld {
18 name: String,
20 },
21
22 #[error("ref '{name}' did not match expected state")]
24 ExpectedMismatch {
25 name: String,
27 expected: Expected,
29 actual: Option<RawRef>,
31 },
32
33 #[error("cannot lock ref: {}", reason.lock_message_suffix())]
35 NameUnavailable {
36 reason: RefnameUnavailable,
38 },
39
40 #[error("multiple updates for ref '{name}' not allowed")]
42 DuplicateUpdate {
43 name: String,
45 },
46
47 #[error("symbolic ref loop or chain too deep")]
49 SymrefLoop,
50
51 #[error("ref not found: {name}")]
53 NotFound {
54 name: String,
56 },
57
58 #[error("corrupt ref store: {0}")]
60 Corrupt(String),
61
62 #[error("{}", crate::git_dir::io_error::format_git_dir_io_message(.path, *operation, &Self::git_dir_io_source(*.os_error)))]
64 GitDirPathIo {
65 path: String,
67 operation: GitDirPathOperation,
69 os_error: i32,
71 },
72
73 #[error("refusing to update ref with bad name '{name}'")]
78 InvalidRefName {
79 name: String,
81 },
82
83 #[error("refusing to point ref '{name}' at the null object id")]
89 NullOid {
90 name: String,
92 },
93
94 #[error(transparent)]
96 InvalidReflog(#[from] crate::ident::SignatureError),
97
98 #[error(transparent)]
102 Backend(BackendError),
103}
104
105impl RefStoreError {
106 pub(crate) fn git_dir_path_io(
107 path: String,
108 operation: GitDirPathOperation,
109 source: std::io::Error,
110 ) -> Self {
111 Self::GitDirPathIo {
112 path,
113 operation,
114 os_error: source.raw_os_error().unwrap_or(0),
115 }
116 }
117
118 pub(crate) fn git_dir_io_source(os_error: i32) -> std::io::Error {
119 if os_error == 0 {
120 std::io::Error::from(std::io::ErrorKind::Other)
121 } else {
122 std::io::Error::from_raw_os_error(os_error)
123 }
124 }
125
126 pub(crate) fn not_found(name: &str) -> Self {
127 Self::NotFound {
128 name: name.to_owned(),
129 }
130 }
131
132 pub fn backend(err: impl std::error::Error + Send + Sync + 'static) -> Self {
134 Self::Backend(BackendError::new(err))
135 }
136}
137
138#[derive(Clone)]
143pub struct BackendError(Arc<dyn std::error::Error + Send + Sync + 'static>);
144
145impl BackendError {
146 pub fn new(err: impl std::error::Error + Send + Sync + 'static) -> Self {
148 Self(Arc::new(err))
149 }
150
151 #[must_use]
153 pub fn get_ref(&self) -> &(dyn std::error::Error + Send + Sync + 'static) {
154 self.0.as_ref()
155 }
156
157 #[must_use]
159 pub fn downcast_ref<E: std::error::Error + 'static>(&self) -> Option<&E> {
160 self.0.downcast_ref::<E>()
161 }
162}
163
164impl fmt::Debug for BackendError {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 fmt::Debug::fmt(&self.0, f)
167 }
168}
169
170impl fmt::Display for BackendError {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 fmt::Display::fmt(&self.0, f)
173 }
174}
175
176impl std::error::Error for BackendError {
177 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
178 self.0.source()
179 }
180}
181
182impl PartialEq for BackendError {
183 fn eq(&self, other: &Self) -> bool {
184 Arc::ptr_eq(&self.0, &other.0)
185 }
186}
187
188impl Eq for BackendError {}
189
190impl From<BackendError> for RefStoreError {
191 fn from(err: BackendError) -> Self {
192 Self::Backend(err)
193 }
194}
195
196impl From<RefnameUnavailable> for RefStoreError {
197 fn from(reason: RefnameUnavailable) -> Self {
198 Self::NameUnavailable { reason }
199 }
200}