Skip to main content

weavatrix_git/
error.rs

1use std::{fmt, io};
2
3pub type Result<T> = std::result::Result<T, GitError>;
4
5#[derive(Debug)]
6pub enum GitError {
7    Io(io::Error),
8    NotRepository(String),
9    InvalidFormat(String),
10    NotFound(String),
11    Unsupported(String),
12    LimitExceeded {
13        resource: &'static str,
14        limit: usize,
15    },
16}
17
18impl fmt::Display for GitError {
19    fn fmt(&self, output: &mut fmt::Formatter<'_>) -> fmt::Result {
20        match self {
21            Self::Io(error) => write!(output, "I/O error: {error}"),
22            Self::NotRepository(message) => write!(output, "not a Git repository: {message}"),
23            Self::InvalidFormat(message) => write!(output, "invalid Git data: {message}"),
24            Self::NotFound(message) => write!(output, "Git object not found: {message}"),
25            Self::Unsupported(message) => write!(output, "unsupported Git feature: {message}"),
26            Self::LimitExceeded { resource, limit } => {
27                write!(output, "{resource} exceeds configured limit {limit}")
28            }
29        }
30    }
31}
32
33impl std::error::Error for GitError {
34    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
35        match self {
36            Self::Io(error) => Some(error),
37            _ => None,
38        }
39    }
40}
41
42impl From<io::Error> for GitError {
43    fn from(error: io::Error) -> Self {
44        Self::Io(error)
45    }
46}
47
48pub(crate) fn invalid(message: impl Into<String>) -> GitError {
49    GitError::InvalidFormat(message.into())
50}
51
52#[cfg(test)]
53mod tests {
54    use std::{error::Error, io};
55
56    use super::GitError;
57
58    #[test]
59    fn formats_every_error_variant() {
60        let errors = [
61            GitError::Io(io::Error::other("disk")),
62            GitError::NotRepository("path".to_owned()),
63            GitError::InvalidFormat("bytes".to_owned()),
64            GitError::NotFound("object".to_owned()),
65            GitError::Unsupported("feature".to_owned()),
66            GitError::LimitExceeded {
67                resource: "depth",
68                limit: 4,
69            },
70        ];
71        for error in errors {
72            assert!(!error.to_string().is_empty());
73        }
74        assert!(GitError::Io(io::Error::other("disk")).source().is_some());
75        assert!(GitError::NotFound("x".to_owned()).source().is_none());
76    }
77}