diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..3b798db --- /dev/null +++ b/src/error.rs @@ -0,0 +1,93 @@ +use std::path::PathBuf; +use std::fmt; + +#[derive(Debug)] +pub enum Error { + NotGitRepository, + NoChanges, + GitRepositoryError(git2::Error), + FileReadError(PathBuf, std::io::Error), + ConfigParseError(PathBuf, String), + InvalidConfigFormat(PathBuf, &'static str), + NoCommitTypeDetected, + Cancelled, + Io(std::io::Error), + Json(serde_json::Error), + Yaml(serde_yaml::Error), + Toml(toml::de::Error), + Regex(regex::Error), + UnknownScope(String), + Other(String), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::NotGitRepository => write!(f, "Not a git repository (not found in current directory or parents)"), + Error::NoChanges => write!(f, "No changes to commit"), + Error::GitRepositoryError(e) => write!(f, "Failed to open git repository: {}", e), + Error::FileReadError(path, e) => write!(f, "Failed to read file {}: {}", path.display(), e), + Error::ConfigParseError(path, msg) => write!(f, "Failed to parse config file {}: {}", path.display(), msg), + Error::InvalidConfigFormat(path, expected) => write!(f, "Invalid config format in {}: expected {}", path.display(), expected), + Error::NoCommitTypeDetected => write!(f, "No commit type detected for changes"), + Error::Cancelled => write!(f, "User cancelled the operation"), + Error::Io(e) => write!(f, "IO error: {}", e), + Error::Json(e) => write!(f, "JSON error: {}", e), + Error::Yaml(e) => write!(f, "YAML error: {}", e), + Error::Toml(e) => write!(f, "TOML error: {}", e), + Error::Regex(e) => write!(f, "Regex error: {}", e), + Error::UnknownScope(s) => write!(f, "Unknown scope detected: {}", s), + Error::Other(s) => write!(f, "{}", s), + } + } +} + +impl std::error::Error for Error {} + +impl From for Error { + fn from(e: git2::Error) -> Self { + Error::GitRepositoryError(e) + } +} + +impl From for Error { + fn from(e: std::io::Error) -> Self { + Error::Io(e) + } +} + +impl From for Error { + fn from(e: serde_json::Error) -> Self { + Error::Json(e) + } +} + +impl From for Error { + fn from(e: serde_yaml::Error) -> Self { + Error::Yaml(e) + } +} + +impl From for Error { + fn from(e: toml::de::Error) -> Self { + Error::Toml(e) + } +} + +impl From for Error { + fn from(e: regex::Error) -> Self { + Error::Regex(e) + } +} + +pub type Result = std::result::Result; + +impl Error { + pub fn exit_code(&self) -> i32 { + match self { + Error::NoChanges => 1, + Error::NotGitRepository => 128, + _ => 1, + } + } +}