Skip to main content

git_vet/
error.rs

1use std::fmt;
2
3use thiserror::Error;
4
5use crate::channel::ChannelError;
6use crate::path::{PathError, RepoPath};
7use crate::remote::RemoteError;
8
9#[derive(Debug, Error)]
10pub enum AppError {
11    #[error("git operation failed while {operation}: {details}")]
12    Git {
13        operation: &'static str,
14        details: String,
15    },
16    #[error("repository has no worktree")]
17    MissingWorktree,
18    #[error("path is not valid UTF-8: {0}")]
19    NonUtf8Path(String),
20    #[error("path escapes the repository root: {0}")]
21    PathOutsideRepo(String),
22    #[error("empty paths are not valid tracked files")]
23    EmptyPath,
24    #[error("repo path is invalid: {path}: {details}")]
25    InvalidRepoPath { path: String, details: &'static str },
26    #[error("path is not tracked at HEAD: {0}")]
27    PathNotTracked(RepoPath),
28    #[error("path is a submodule/gitlink and is out of scope: {0}")]
29    PathIsSubmodule(RepoPath),
30    #[error("failed to read vetignore file: {0}")]
31    Vetignore(String),
32    #[error("missing git config user.name")]
33    MissingUserName,
34    #[error("missing git config user.email")]
35    MissingUserEmail,
36    #[error("git config {key} is not valid UTF-8: {details}")]
37    NonUtf8GitConfig { key: &'static str, details: String },
38    #[error(
39        "target paths have uncommitted working-tree changes; rerun with --allow-dirty to proceed with committed HEAD contents"
40    )]
41    DirtyPathsRequireAllowDirty,
42    #[error("aborted because target paths have uncommitted working-tree changes")]
43    DirtyPathsDeclined,
44    #[error("invalid review channel {channel:?}: {details}")]
45    InvalidChannel { channel: String, details: String },
46    #[error("sync remote error: {0}")]
47    Remote(#[from] RemoteError),
48    #[error("I/O error: {0}")]
49    Io(#[from] std::io::Error),
50    #[error("JSON error: {0}")]
51    Json(#[from] serde_json::Error),
52}
53
54impl From<PathError> for AppError {
55    fn from(error: PathError) -> Self {
56        match error {
57            PathError::NonUtf8Path(path) => Self::NonUtf8Path(path),
58            PathError::PathOutsideRepo(path) => Self::PathOutsideRepo(path),
59            PathError::EmptyPath => Self::EmptyPath,
60            PathError::InvalidRepoPath { path, details } => Self::InvalidRepoPath { path, details },
61        }
62    }
63}
64
65impl From<ChannelError> for AppError {
66    fn from(error: ChannelError) -> Self {
67        Self::InvalidChannel {
68            channel: error.channel,
69            details: error.details,
70        }
71    }
72}
73
74pub fn git_error(operation: &'static str, source: impl fmt::Display) -> AppError {
75    AppError::Git {
76        operation,
77        details: source.to_string(),
78    }
79}