use std::sync::Arc;
use async_trait::async_trait;
use crate::result::Result;
pub mod apt;
#[cfg(unix)]
pub mod brew;
pub mod dnf;
pub mod pacman;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PackageRequest {
pub name: String,
pub version: Option<String>,
}
impl std::fmt::Display for PackageRequest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.version {
Some(v) => write!(f, "{}@{}", self.name, v),
None => write!(f, "{}", self.name),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PackageState {
Installed {
version: String,
},
Missing,
VersionMismatch {
installed: String,
},
}
#[derive(Debug, Clone)]
pub struct PackageStatus {
pub request: PackageRequest,
pub state: PackageState,
}
#[derive(Debug, Default)]
pub struct InstallOpts {
pub dry_run: bool,
pub update: bool,
}
#[async_trait]
pub trait SystemPackageManager: Send + Sync {
fn name(&self) -> &'static str;
fn is_available(&self) -> bool;
fn unavailable_reason(&self) -> String;
async fn installed(&self, pkgs: &[PackageRequest]) -> Result<Vec<PackageStatus>>;
async fn install(&self, pkgs: &[PackageRequest], opts: &InstallOpts) -> Result<()>;
async fn upgrade(&self, pkgs: &[PackageRequest], opts: &InstallOpts) -> Result<()> {
self.install(pkgs, opts).await
}
fn supports_version_pins(&self) -> bool {
true
}
}
pub fn all_managers() -> Vec<Arc<dyn SystemPackageManager>> {
vec![
Arc::new(apt::AptManager::new()),
#[cfg(unix)]
Arc::new(brew::BrewManager::new()),
Arc::new(dnf::DnfManager::new()),
Arc::new(pacman::PacmanManager::new()),
]
}
pub fn get_manager(name: &str) -> Option<Arc<dyn SystemPackageManager>> {
all_managers().into_iter().find(|m| m.name() == name)
}