smirrors 0.1.0

Automatic mirror list updater for Linux distributions
Documentation
//! Distribution-specific handlers for mirror management
//!
//! This module provides abstraction for different Linux distributions
//! and their package manager mirror configurations.

pub mod apt;
pub mod detector;
pub mod dnf;
pub mod pacman;
pub mod zypper;

use crate::core::Mirror;
use anyhow::Result;

// Re-export commonly used types
pub use apt::AptHandler;
pub use detector::{DistroDetector, DistroInfo};
pub use dnf::DnfHandler;
pub use pacman::PacmanHandler;
pub use zypper::ZypperHandler;

/// Distribution handler trait
///
/// Implementations of this trait provide distribution-specific logic
/// for fetching, updating, and managing mirror configurations.
#[async_trait::async_trait]
pub trait DistroHandler: Send + Sync {
    /// Get distribution name
    fn name(&self) -> &str;

    /// Detect if this handler applies to current system
    fn detect(&self) -> bool;

    /// Get list of available mirrors from distribution
    async fn get_available_mirrors(&self) -> Result<Vec<Mirror>>;

    /// Get currently configured mirrors
    fn get_current_mirrors(&self) -> Result<Vec<Mirror>>;

    /// Update mirror list with new mirrors
    fn update_mirrors(&self, mirrors: &[Mirror]) -> Result<()>;

    /// Create backup of current configuration
    fn backup(&self) -> Result<()>;

    /// Restore from backup
    fn restore_backup(&self) -> Result<()>;

    /// Validate mirror configuration
    fn validate(&self) -> Result<bool>;
}

/// Distribution type enumeration
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Distro {
    Debian,
    Ubuntu,
    Fedora,
    RHEL,
    Arch,
    Manjaro,
    OpenSUSE,
    Unknown,
}

impl Distro {
    /// Get distribution name as string
    pub fn as_str(&self) -> &str {
        match self {
            Self::Debian => "Debian",
            Self::Ubuntu => "Ubuntu",
            Self::Fedora => "Fedora",
            Self::RHEL => "RHEL",
            Self::Arch => "Arch",
            Self::Manjaro => "Manjaro",
            Self::OpenSUSE => "openSUSE",
            Self::Unknown => "Unknown",
        }
    }

    /// Get the appropriate handler for this distribution
    pub fn get_handler(&self) -> Option<Box<dyn DistroHandler>> {
        match self {
            Self::Debian | Self::Ubuntu => Some(Box::new(AptHandler::new())),
            Self::Fedora | Self::RHEL => Some(Box::new(DnfHandler::new())),
            Self::Arch | Self::Manjaro => Some(Box::new(PacmanHandler::new())),
            Self::OpenSUSE => Some(Box::new(ZypperHandler::new())),
            Self::Unknown => None,
        }
    }
}

/// Detect the current distribution and return appropriate handler
pub fn detect_handler() -> Result<Box<dyn DistroHandler>> {
    let distro = DistroDetector::detect()?;

    distro.get_handler()
        .ok_or_else(|| anyhow::anyhow!("Unsupported distribution: {:?}", distro))
}

/// Get all available handlers (for testing purposes)
pub fn get_all_handlers() -> Vec<Box<dyn DistroHandler>> {
    vec![
        Box::new(AptHandler::new()),
        Box::new(DnfHandler::new()),
        Box::new(PacmanHandler::new()),
        Box::new(ZypperHandler::new()),
    ]
}