use miette::Diagnostic;
use soar_utils::error::{PathError, UtilsError};
use thiserror::Error;
#[derive(Error, Diagnostic, Debug)]
pub enum ConfigError {
#[error(transparent)]
#[diagnostic(
code(soar_config::toml_serialize),
help("Check your configuration structure for invalid values")
)]
TomlSerError(#[from] toml::ser::Error),
#[error(transparent)]
#[diagnostic(
code(soar_config::toml_deserialize),
help("Check your config.toml syntax and structure")
)]
TomlDeError(#[from] toml::de::Error),
#[error("Configuration file already exists")]
#[diagnostic(
code(soar_config::already_exists),
help("Remove the existing config file or use a different location")
)]
ConfigAlreadyExists,
#[error("Packages configuration file not found: {0}")]
#[diagnostic(
code(soar_config::packages_not_found),
help("Create a packages.toml file or run `soar defpackages` to generate one")
)]
PackagesConfigNotFound(String),
#[error("Packages configuration file already exists")]
#[diagnostic(
code(soar_config::packages_already_exists),
help("Remove the existing packages.toml file or use a different location")
)]
PackagesConfigAlreadyExists,
#[error("Invalid profile: {0}")]
#[diagnostic(
code(soar_config::invalid_profile),
help("Check available profiles in your config file")
)]
InvalidProfile(String),
#[error("Missing default profile: {0}")]
#[diagnostic(
code(soar_config::missing_default_profile),
help("Ensure the default_profile field references an existing profile")
)]
MissingDefaultProfile(String),
#[error("Missing profile: {0}")]
#[diagnostic(
code(soar_config::missing_profile),
help("Add the profile to your configuration or use an existing one")
)]
MissingProfile(String),
#[error("Invalid repository name: {0}")]
#[diagnostic(code(soar_config::invalid_repository))]
InvalidRepository(String),
#[error("Invalid repository URL: {0}")]
#[diagnostic(code(soar_config::invalid_repository_url))]
InvalidRepositoryUrl(String),
#[error("Reserved repository name 'local' cannot be used")]
#[diagnostic(
code(soar_config::reserved_repo_name),
help("Choose a different name for your repository")
)]
ReservedRepositoryName,
#[error("Duplicate repository name: {0}")]
#[diagnostic(
code(soar_config::duplicate_repo),
help("Each repository must have a unique name")
)]
DuplicateRepositoryName(String),
#[error("Repository '{0}' has signature verification enabled but no pubkey configured")]
#[diagnostic(
code(soar_config::missing_pubkey),
help("Provide a pubkey for the repository or disable signature_verification")
)]
MissingPubkey(String),
#[error(transparent)]
#[diagnostic(code(soar_config::io))]
IoError(#[from] std::io::Error),
#[error(transparent)]
#[diagnostic(code(soar_config::utils))]
Utils(#[from] soar_utils::error::UtilsError),
#[error(transparent)]
#[diagnostic(code(soar_config::toml))]
Toml(#[from] toml_edit::TomlError),
#[error("Encountered unexpected TOML item: {0}")]
#[diagnostic(code(soar_config::unexpected_toml_item))]
UnexpectedTomlItem(String),
#[error("Failed to annotate first table in array: {0}")]
#[diagnostic(code(soar_config::annotate_first_table))]
AnnotateFirstTable(String),
#[error("{0}")]
#[diagnostic(code(soar_config::custom))]
Custom(String),
}
impl From<PathError> for ConfigError {
fn from(err: PathError) -> Self {
Self::Utils(UtilsError::Path(err))
}
}
impl From<soar_utils::error::BytesError> for ConfigError {
fn from(err: soar_utils::error::BytesError) -> Self {
Self::Utils(UtilsError::Bytes(err))
}
}
impl From<soar_utils::error::FileSystemError> for ConfigError {
fn from(err: soar_utils::error::FileSystemError) -> Self {
Self::Utils(UtilsError::FileSystem(err))
}
}
pub type Result<T> = std::result::Result<T, ConfigError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = ConfigError::ConfigAlreadyExists;
assert_eq!(err.to_string(), "Configuration file already exists");
let err = ConfigError::InvalidProfile("test".to_string());
assert_eq!(err.to_string(), "Invalid profile: test");
let err = ConfigError::DuplicateRepositoryName("duplicate".to_string());
assert_eq!(err.to_string(), "Duplicate repository name: duplicate");
}
#[test]
fn test_error_from_conversions() {
let path_err = soar_utils::error::PathError::MissingEnvVar {
var: "SOAR_ROOT".to_string(),
input: "$SOR_ROOT/test".to_string(),
};
let config_err: ConfigError = path_err.into();
assert!(matches!(config_err, ConfigError::Utils(_)));
}
}