Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Per-Backend missing resolution #62

Merged
merged 11 commits into from
Feb 8, 2025
26 changes: 21 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- New subcommand `metapac clean-cache`! (#61)

Allows you to clear the caches for all or selective backends.
`metapac clean-cache arch apt` to clean just the `arch` and `apt`
backends and just `metapac clear-cache` to clear all backends.
- A new per-package `systemwide` setting for `flatpak` packages. (#62)

### Changed

- The `flatpak_systemwide` has been renamed to
`flatpak_default_systemwide` to allow for a new `systemwide`
per-package setting for `flatpak` packages (#62)

### Removed

- The `optional_deps` options on `arch` packages has been removed
since it not a feature of the `arch` backend package managers and
was handled by `metapac`, in the interest of simplicity this odd bit
of logic has been removed (this also it makes the
code nicer). Instead if you have multiple packages
which you want installed only if another package is installed
consider using a comment and whitespace to separate them
visually in your group files so that it is obvious when reading or
modififying them that they are linked. You could even separate the
packages out into another group file and include or uninclude the
entire group via symlinking or the `hostname_groups` config feature. (#62)

### Fixed

Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ support for additional backends are welcome!
# Default: "pacman"
arch_package_manager = "paru"

# Whether to install flatpak packages systemwide or for the current user.
# Whether to default to installing flatpak packages systemwide or for the current user.
# This setting can be overridden on a per-package basis using { systemwide = false|true }.
# Default: true
flatpak_systemwide = true
flatpak_default_systemwide = true

# Backends to disable from all metapac behavior. See the README.md for
# the list of backend names
Expand Down Expand Up @@ -137,8 +138,7 @@ server = ["example_group"]

arch = [
"metapac",
# optional_deps: additional packages to install with this package, short-form syntax only
{ package = "metapac", optional_deps = ["git"] }
{ package = "metapac" }
]
apt = [
"metapac",
Expand All @@ -160,15 +160,18 @@ dnf = [
]
flatpak = [
"metapac",
{ package = "metapac", remote = "flathub" }
{ package = "metapac", remote = "flathub", systemwide = false }
]
pipx = [
"metapac",
{ package = "metapac" }
]
rustup = [
"stable",
# components: extra non-default components to install with this toolchain
# components: extra non-default components to install for this toolchain

# see https://rust-lang.github.io/rustup/concepts/components.html
# for more details
{ package = "stable", components = ["rust-analyzer"] }
]
snap = [
Expand Down
85 changes: 31 additions & 54 deletions src/backends/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ macro_rules! any {
$( AnyBackend::$upper_backend => $upper_backend::version(config), )*
}
}
pub fn remove_packages(&self, packages: &BTreeSet<String>, no_confirm: bool, config: &Config) -> Result<()> {
pub fn remove(&self, packages: &BTreeSet<String>, no_confirm: bool, config: &Config) -> Result<()> {
match self {
$( AnyBackend::$upper_backend => $upper_backend::remove_packages(packages, no_confirm, config), )*
$( AnyBackend::$upper_backend => $upper_backend::remove(packages, no_confirm, config), )*
}
}
}
Expand Down Expand Up @@ -99,12 +99,6 @@ macro_rules! package_ids {
}
}

pub fn remove(&mut self, backend: AnyBackend, package: &str) -> bool {
match backend {
$( AnyBackend::$upper_backend => self.$lower_backend.remove(package) ),*
}
}

pub fn difference(&self, other: &Self) -> Self {
let mut output = Self::default();

Expand All @@ -115,10 +109,10 @@ macro_rules! package_ids {
output
}

pub fn remove_packages(&self, no_confirm: bool, config: &Config) -> Result<()> {
pub fn remove(&self, no_confirm: bool, config: &Config) -> Result<()> {
$(
if is_enabled(AnyBackend::$upper_backend, config) {
AnyBackend::$upper_backend.remove_packages(&self.$lower_backend, no_confirm, config)?;
AnyBackend::$upper_backend.remove(&self.$lower_backend, no_confirm, config)?;
}
)*

Expand All @@ -144,45 +138,15 @@ macro_rules! package_ids {
}
apply_public_backends!(package_ids);

macro_rules! query_infos {
($(($upper_backend:ident, $lower_backend:ident)),*) => {
#[derive(Debug, Clone, Default)]
pub struct QueryInfos {
$(
pub $lower_backend: BTreeMap<String, <$upper_backend as Backend>::QueryInfo>,
)*
}
impl QueryInfos {
append!($(($upper_backend, $lower_backend)),*);
is_empty!($(($upper_backend, $lower_backend)),*);
to_package_ids!($(($upper_backend, $lower_backend)),*);

pub fn query_installed_packages(config: &Config) -> Result<Self> {
Ok(Self {
$(
$lower_backend:
if is_enabled(AnyBackend::$upper_backend, config) {
$upper_backend::query_installed_packages(config)?
} else {
Default::default()
},
)*
})
}
}
}
}
apply_public_backends!(query_infos);

macro_rules! raw_install_options {
macro_rules! raw_options {
($(($upper_backend:ident, $lower_backend:ident)),*) => {
#[derive(Debug, Clone, Default)]
pub struct RawInstallOptions {
pub struct RawOptions {
$(
pub $lower_backend: Vec<(String, <$upper_backend as Backend>::InstallOptions)>,
pub $lower_backend: Vec<(String, <$upper_backend as Backend>::Options)>,
)*
}
impl RawInstallOptions {
impl RawOptions {
append!($(($upper_backend, $lower_backend)),*);

pub fn to_raw_package_ids(&self) -> RawPackageIds {
Expand All @@ -193,45 +157,58 @@ macro_rules! raw_install_options {
}
}
}
apply_public_backends!(raw_install_options);
apply_public_backends!(raw_options);

macro_rules! install_options {
macro_rules! options {
($(($upper_backend:ident, $lower_backend:ident)),*) => {
#[derive(Debug, Clone, Default)]
#[allow(non_snake_case)]
pub struct InstallOptions {
pub struct Options {
$(
pub $lower_backend: BTreeMap<String, <$upper_backend as Backend>::InstallOptions>,
pub $lower_backend: BTreeMap<String, <$upper_backend as Backend>::Options>,
)*
}
impl InstallOptions {
impl Options {
append!($(($upper_backend, $lower_backend)),*);
is_empty!($(($upper_backend, $lower_backend)),*);
to_package_ids!($(($upper_backend, $lower_backend)),*);

pub fn map_install_packages(mut self, config: &Config) -> Result<Self> {
pub fn map_required(mut self, config: &Config) -> Result<Self> {
$(
if is_enabled(AnyBackend::$upper_backend, config) {
self.$lower_backend = $upper_backend::map_managed_packages(self.$lower_backend, config)?;
self.$lower_backend = $upper_backend::map_required(self.$lower_backend, config)?;
}
)*

Ok(self)
}

pub fn install_packages(self, no_confirm: bool, config: &Config) -> Result<()> {
pub fn install(self, no_confirm: bool, config: &Config) -> Result<()> {
$(
if is_enabled(AnyBackend::$upper_backend, config) {
$upper_backend::install_packages(&self.$lower_backend, no_confirm, config)?;
$upper_backend::install(&self.$lower_backend, no_confirm, config)?;
}
)*

Ok(())
}

pub fn query(config: &Config) -> Result<Self> {
Ok(Self {
$(
$lower_backend:
if is_enabled(AnyBackend::$upper_backend, config) {
$upper_backend::query(config)?
} else {
Default::default()
},
)*
})
}
}
}
}
apply_public_backends!(install_options);
apply_public_backends!(options);

fn is_enabled(backend: AnyBackend, config: &Config) -> bool {
!config
Expand Down
31 changes: 17 additions & 14 deletions src/backends/apt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,20 @@ use crate::prelude::*;
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)]
pub struct Apt;

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AptQueryInfo {}

#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AptInstallOptions {}
pub struct AptOptions {}

impl Backend for Apt {
type QueryInfo = AptQueryInfo;
type InstallOptions = AptInstallOptions;
type Options = AptOptions;

fn map_managed_packages(
packages: BTreeMap<String, Self::InstallOptions>,
fn map_required(
packages: BTreeMap<String, Self::Options>,
_: &Config,
) -> Result<BTreeMap<String, Self::InstallOptions>> {
) -> Result<BTreeMap<String, Self::Options>> {
Ok(packages)
}

fn query_installed_packages(config: &Config) -> Result<BTreeMap<String, Self::QueryInfo>> {
fn query(config: &Config) -> Result<BTreeMap<String, Self::Options>> {
if Self::version(config).is_err() {
return Ok(BTreeMap::new());
}
Expand All @@ -41,12 +37,12 @@ impl Backend for Apt {

Ok(explicit
.lines()
.map(|x| (x.to_string(), AptQueryInfo {}))
.map(|x| (x.to_string(), Self::Options {}))
.collect())
}

fn install_packages(
packages: &BTreeMap<String, Self::InstallOptions>,
fn install(
packages: &BTreeMap<String, Self::Options>,
no_confirm: bool,
_: &Config,
) -> Result<()> {
Expand All @@ -63,7 +59,7 @@ impl Backend for Apt {
Ok(())
}

fn remove_packages(packages: &BTreeSet<String>, no_confirm: bool, _: &Config) -> Result<()> {
fn remove(packages: &BTreeSet<String>, no_confirm: bool, _: &Config) -> Result<()> {
if !packages.is_empty() {
run_command(
["apt-get", "remove"]
Expand All @@ -86,4 +82,11 @@ impl Backend for Apt {
fn version(_: &Config) -> Result<String> {
run_command_for_stdout(["apt", "--version"], Perms::Same, false)
}

fn missing(required: Self::Options, installed: Option<Self::Options>) -> Option<Self::Options> {
match installed {
Some(_) => None,
None => Some(required),
}
}
}
Loading
Loading