Backend trait refactors
- Refactor the confusing/bodgy consts backend macro to use a single `BackendInfo` struct - Combine `supports_as_dependency()` and the `switches_dependency` into a single `Option` type as that is a better representation as it is an optional backend feature. - Add more types like `Packages`, `Sections` for uniformity. - Added a crate-private prelude and switches all imports to use a prelude glob import (excluding functions because it's nice to only be importing types) - Refactored Backend section name in logging by implementing Display for `AnyBackend` that just prints the `section`
This commit is contained in:
@@ -1,23 +1,53 @@
|
||||
pub mod actual;
|
||||
pub mod backend_trait;
|
||||
pub mod macros;
|
||||
mod root;
|
||||
pub mod todo_per_backend;
|
||||
|
||||
use crate::backend::backend_trait::Switches;
|
||||
use crate::backend::backend_trait::Text;
|
||||
use crate::Group;
|
||||
use crate::Groups;
|
||||
use crate::Package;
|
||||
use anyhow::Result;
|
||||
use backend_trait::Backend;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Display;
|
||||
|
||||
use self::actual::{
|
||||
fedora::Fedora, flatpak::Flatpak, python::Python, rust::Rust, rustup::Rustup, void::Void,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
// A backend with its associated managed packages
|
||||
pub struct ManagedBackend {
|
||||
/// All managed packages for this backend, i.e. all packages
|
||||
/// under the corresponding section in all group files.
|
||||
pub packages: Packages,
|
||||
pub any_backend: AnyBackend,
|
||||
}
|
||||
impl ManagedBackend {
|
||||
/// Get unmanaged packages, sorted alphabetically.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the backend fails to get the explicitly installed packages.
|
||||
pub fn get_unmanaged_packages_sorted(&self) -> Result<Vec<Package>> {
|
||||
let installed = self
|
||||
.any_backend
|
||||
.get_explicitly_installed_packages()
|
||||
.context("could not get explicitly installed packages")?;
|
||||
let mut diff: Vec<_> = installed.difference(&self.packages).cloned().collect();
|
||||
diff.sort_unstable();
|
||||
Ok(diff)
|
||||
}
|
||||
|
||||
/// Get missing packages, sorted alphabetically.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the backend fails to get the installed packages.
|
||||
pub fn get_missing_packages_sorted(&self) -> Result<Vec<Package>> {
|
||||
let installed = self
|
||||
.any_backend
|
||||
.get_all_installed_packages()
|
||||
.context("could not get installed packages")?;
|
||||
let mut diff: Vec<_> = self.packages.difference(&installed).cloned().collect();
|
||||
diff.sort_unstable();
|
||||
Ok(diff)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[enum_dispatch::enum_dispatch(Backend)]
|
||||
pub enum AnyBackend {
|
||||
#[cfg(feature = "arch")]
|
||||
@@ -31,22 +61,44 @@ pub enum AnyBackend {
|
||||
Rustup(Rustup),
|
||||
Void(Void),
|
||||
}
|
||||
|
||||
impl AnyBackend {
|
||||
/// Returns an iterator of every variant of backend.
|
||||
pub fn iter() -> impl Iterator<Item = Self> {
|
||||
pub fn all(config: &Config) -> impl Iterator<Item = Self> {
|
||||
vec![
|
||||
#[cfg(feature = "arch")]
|
||||
Self::Arch(actual::arch::Arch::new()),
|
||||
Self::Arch(actual::arch::Arch::new(config)),
|
||||
#[cfg(feature = "debian")]
|
||||
Self::Debian(actual::debian::Debian::new()),
|
||||
Self::Flatpak(Flatpak::new()),
|
||||
Self::Flatpak(Flatpak::new(config)),
|
||||
Self::Fedora(Fedora::new()),
|
||||
Self::Python(Python::new()),
|
||||
Self::Python(Python::new(config)),
|
||||
Self::Rust(Rust::new()),
|
||||
Self::Rustup(Rustup::new()),
|
||||
Self::Void(Void::new()),
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn from_section(section: &str, config: &Config) -> Result<Self> {
|
||||
match section {
|
||||
#[cfg(feature = "arch")]
|
||||
"arch" => Ok(Self::Arch(actual::arch::Arch::new(config))),
|
||||
#[cfg(feature = "debian")]
|
||||
"debian" => Ok(Self::Debian(actual::debian::Debian::new())),
|
||||
"flatpak" => Ok(Self::Flatpak(Flatpak::new(config))),
|
||||
"fedora" => Ok(Self::Fedora(Fedora::new())),
|
||||
"python" => Ok(Self::Python(Python::new(config))),
|
||||
"rust" => Ok(Self::Rust(Rust::new())),
|
||||
"rustup" => Ok(Self::Rustup(Rustup::new())),
|
||||
"void" => Ok(Self::Void(Void::new())),
|
||||
_ => Err(anyhow::anyhow!(
|
||||
"no matching backend for the section: {section}"
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Display for AnyBackend {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.backend_info().section)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user