smirrors 0.1.0

Automatic mirror list updater for Linux distributions
Documentation
use thiserror::Error;

/// Main error type for SMirrors operations
#[derive(Error, Debug)]
pub enum SMirrorsError {
    #[error("Failed to detect distribution")]
    DistroDetectionFailed,

    #[error("Unsupported distribution: {0}")]
    UnsupportedDistro(String),

    #[error("Mirror test failed for {url}: {reason}")]
    MirrorTestFailed { url: String, reason: String },

    #[error("Permission denied: {0}. Try running with sudo")]
    PermissionDenied(String),

    #[error("Configuration error: {0}")]
    ConfigError(String),

    #[error("Invalid configuration value for {key}: {value}")]
    InvalidConfigValue { key: String, value: String },

    #[error("Configuration file not found at {0}")]
    ConfigNotFound(String),

    #[error("IO error: {0}")]
    IoError(#[from] std::io::Error),

    #[error("Network error: {0}")]
    NetworkError(#[from] reqwest::Error),

    #[error("Database error: {0}")]
    DatabaseError(#[from] rusqlite::Error),

    #[error("Parse error: {0}")]
    ParseError(String),

    #[error("Regex error: {0}")]
    RegexError(#[from] regex::Error),

    #[error("URL parse error: {0}")]
    UrlError(#[from] url::ParseError),

    #[error("TOML deserialization error: {0}")]
    TomlDeError(#[from] toml::de::Error),

    #[error("TOML serialization error: {0}")]
    TomlSerError(#[from] toml::ser::Error),

    #[error("JSON error: {0}")]
    JsonError(#[from] serde_json::Error),

    #[error("Systemd error: {0}")]
    SystemdError(String),

    #[error("Backup not found: {0}")]
    BackupNotFound(String),

    #[error("Backup restore failed: {0}")]
    BackupRestoreFailed(String),

    #[error("Mirror list empty after filtering")]
    NoMirrorsAvailable,

    #[error("Test timeout after {0} seconds")]
    TestTimeout(u64),

    #[error("Update failed: {0}")]
    UpdateFailed(String),

    #[error("Validation failed: {0}")]
    ValidationFailed(String),

    #[error("Lock file exists at {0}. Another instance may be running")]
    LockFileExists(String),

    #[error("Async task join error: {0}")]
    JoinError(#[from] tokio::task::JoinError),
}

impl SMirrorsError {
    /// Create a permission denied error with context
    pub fn permission_denied(operation: &str) -> Self {
        Self::PermissionDenied(operation.to_string())
    }

    /// Create a config error with context
    pub fn config_error(message: impl Into<String>) -> Self {
        Self::ConfigError(message.into())
    }

    /// Create a parse error with context
    pub fn parse_error(message: impl Into<String>) -> Self {
        Self::ParseError(message.into())
    }

    /// Create a systemd error with context
    pub fn systemd_error(message: impl Into<String>) -> Self {
        Self::SystemdError(message.into())
    }

    /// Create an update failed error with context
    pub fn update_failed(message: impl Into<String>) -> Self {
        Self::UpdateFailed(message.into())
    }

    /// Create a validation failed error with context
    pub fn validation_failed(message: impl Into<String>) -> Self {
        Self::ValidationFailed(message.into())
    }

    /// Check if error is a network-related error
    pub fn is_network_error(&self) -> bool {
        matches!(self, Self::NetworkError(_) | Self::MirrorTestFailed { .. })
    }

    /// Check if error is a permission error
    pub fn is_permission_error(&self) -> bool {
        matches!(self, Self::PermissionDenied(_))
    }

    /// Check if error is recoverable
    pub fn is_recoverable(&self) -> bool {
        matches!(
            self,
            Self::NetworkError(_)
                | Self::MirrorTestFailed { .. }
                | Self::TestTimeout(_)
        )
    }
}