1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, JJError>;
7
8#[derive(Error, Debug, Clone, PartialEq)]
10pub enum JJError {
11 #[error("jj command not found. Please install Jujutsu: https://github.com/jj-vcs/jj")]
13 JJNotFound,
14
15 #[error("jj command failed: {0}")]
17 CommandFailed(String),
18
19 #[error("Failed to parse jj output: {0}")]
21 ParseError(String),
22
23 #[error("Operation {0} not found")]
25 OperationNotFound(String),
26
27 #[error("Conflict resolution failed: {0}")]
29 ConflictResolutionFailed(String),
30
31 #[error("Invalid configuration: {0}")]
33 InvalidConfig(String),
34
35 #[error("I/O error: {0}")]
37 IoError(String),
38
39 #[error("Serialization error: {0}")]
41 SerializationError(String),
42
43 #[error("Unknown error: {0}")]
45 Unknown(String),
46
47 #[error("MCP error: {0}")]
49 MCPError(String),
50}
51
52impl JJError {
53 pub fn message(&self) -> String {
55 self.to_string()
56 }
57
58 pub fn is_recoverable(&self) -> bool {
60 matches!(
61 self,
62 JJError::CommandFailed(_) | JJError::ConflictResolutionFailed(_)
63 )
64 }
65}
66
67impl From<std::io::Error> for JJError {
68 fn from(err: std::io::Error) -> Self {
69 JJError::IoError(err.to_string())
70 }
71}
72
73impl From<serde_json::Error> for JJError {
74 fn from(err: serde_json::Error) -> Self {
75 JJError::SerializationError(err.to_string())
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_error_display() {
85 let err = JJError::JJNotFound;
86 assert!(err.to_string().contains("jj command not found"));
87 }
88
89 #[test]
90 fn test_recoverable() {
91 assert!(JJError::CommandFailed("test".into()).is_recoverable());
92 assert!(!JJError::JJNotFound.is_recoverable());
93 }
94}