1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum SyncError {
5 #[error("Not a git repository: {path}")]
6 NotARepository { path: String },
7
8 #[error("Repository in unsafe state: {state}")]
9 UnsafeRepositoryState { state: String },
10
11 #[error("Not on a branch (detached HEAD)")]
12 DetachedHead,
13
14 #[error("No remote configured for branch {branch}")]
15 NoRemoteConfigured { branch: String },
16
17 #[error("Branch {branch} not configured for sync")]
18 BranchNotConfigured { branch: String },
19
20 #[error("Manual intervention required: {reason}")]
21 ManualInterventionRequired { reason: String },
22
23 #[error("Network error: {0}")]
24 NetworkError(String),
25
26 #[error("Git error: {0}")]
27 GitError(#[from] git2::Error),
28
29 #[error("IO error: {0}")]
30 IoError(#[from] std::io::Error),
31
32 #[error("Watch error: {0}")]
33 WatchError(String),
34
35 #[error("Task error: {0}")]
36 TaskError(String),
37
38 #[error("Other error: {0}")]
39 Other(String),
40}
41
42impl SyncError {
43 pub fn exit_code(&self) -> i32 {
45 match self {
46 SyncError::NotARepository { .. } => 128, SyncError::UnsafeRepositoryState { .. } => 2,
48 SyncError::DetachedHead => 2,
49 SyncError::NoRemoteConfigured { .. } => 2,
50 SyncError::BranchNotConfigured { .. } => 1,
51 SyncError::ManualInterventionRequired { .. } => 1,
52 SyncError::NetworkError(_) => 3,
53 SyncError::GitError(e) => {
54 match e.code() {
56 git2::ErrorCode::NotFound => 128,
57 git2::ErrorCode::Conflict => 1,
58 git2::ErrorCode::Locked => 2,
59 _ => 2,
60 }
61 }
62 SyncError::IoError(_) => 2,
63 SyncError::WatchError(_) => 2,
64 SyncError::TaskError(_) => 2,
65 SyncError::Other(_) => 2,
66 }
67 }
68}
69
70pub type Result<T> = std::result::Result<T, SyncError>;
71
72impl From<notify::Error> for SyncError {
73 fn from(err: notify::Error) -> Self {
74 SyncError::WatchError(err.to_string())
75 }
76}
77
78impl From<tokio::task::JoinError> for SyncError {
79 fn from(err: tokio::task::JoinError) -> Self {
80 SyncError::TaskError(err.to_string())
81 }
82}