Skip to main content

git_vet/
error.rs

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