diff --git a/Cargo.lock b/Cargo.lock index 620d2d1..896830e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -551,7 +551,6 @@ dependencies = [ "itertools", "libc", "log", - "path-absolutize", "pretty_env_logger", "regex", "serde", @@ -559,25 +558,6 @@ dependencies = [ "serde_json", "strum", "toml", - "walkdir", -] - -[[package]] -name = "path-absolutize" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5" -dependencies = [ - "path-dedot", -] - -[[package]] -name = "path-dedot" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" -dependencies = [ - "once_cell", ] [[package]] @@ -712,15 +692,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "serde" version = "1.0.210" @@ -1011,16 +982,6 @@ dependencies = [ "libc", ] -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 71c8935..a2a1a0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,7 @@ rust-version = "1.78" [dependencies] color-eyre = "0.6.3" clap = { version = "4.5.18", features = ["derive"] } -path-absolutize = "3.1.1" regex = { version = "1.10.6", default-features = false, features = ["std"] } -walkdir = "2.5.0" libc = "0.2.159" log = { version = "0.4.22", features = ["std"] } serde = { version = "1.0.210", features = ["derive"] } diff --git a/README.md b/README.md index ffb913f..6e48c70 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ can be set. The listed values are the defaults. ```toml aur_helper = "paru" # AUR helper to use on Arch Linux (paru, yay, ...) -aur_rm_args = [] # additional args to pass to AUR helper when removing packages (optional) +arch_rm_args = [] # additional args to pass to AUR helper when removing packages (optional) disabled_backends = [] # backends that pacdef should not manage, e.g. ["python"], this can reduce runtime if the package manager is notoriously slow (like pip) warn_not_symlinks = true # warn if a group file is not a symlink diff --git a/config.toml b/config.toml index 4cddee3..b478d6f 100644 --- a/config.toml +++ b/config.toml @@ -1,11 +1,19 @@ +# Which arch package manager to use. For example: pacman, paru, yay, +# etc.. +arch_package_manager = "paru" + # Extra arguments passed to pacman when removing an arch package. -aur_rm_args = [""] +arch_rm_args = [""] # Whether to install flatpak packages systemwide or for the current user. flatpak_systemwide = true +# Backends to disable from all pacdef behavior. See the README.md for +# the list of backend names +disabled_backends = ["pip"] + # Which group files apply for which hostnames [hostname_groups] -pc = ["example_config"] -laptop = ["example_config"] -server = ["example_config"] +pc = ["example_group"] +laptop = ["example_group"] +server = ["example_group"] diff --git a/src/backends/all.rs b/src/backends/all.rs index 457f63a..6f77699 100644 --- a/src/backends/all.rs +++ b/src/backends/all.rs @@ -113,7 +113,12 @@ macro_rules! query_infos { pub fn query_installed_packages(config: &Config) -> Result { Ok(Self { $( - $backend: $backend::query_installed_packages(config)?, + $backend: + if is_enabled(&$backend.to_string(), config) { + $backend::query_installed_packages(config)? + } else { + Default::default() + }, )* }) } @@ -138,7 +143,9 @@ macro_rules! install_options { pub fn install_packages(self, no_confirm: bool, config: &Config) -> Result<()> { $( - $backend::install_packages(&self.$backend, no_confirm, config)?; + if is_enabled(&$backend.to_string(), config) { + $backend::install_packages(&self.$backend, no_confirm, config)?; + } )* Ok(()) @@ -164,7 +171,9 @@ macro_rules! modification_options { pub fn modify_packages(self, config: &Config) -> Result<()> { $( - $backend::modify_packages(&self.$backend, config)?; + if is_enabled(&$backend.to_string(), config) { + $backend::modify_packages(&self.$backend, config)?; + } )* Ok(()) @@ -190,7 +199,9 @@ macro_rules! remove_options { pub fn remove_packages(self, no_confirm: bool, config: &Config) -> Result<()> { $( - $backend::remove_packages(&self.$backend, no_confirm, config)?; + if is_enabled(&$backend.to_string(), config) { + $backend::remove_packages(&self.$backend, no_confirm, config)?; + } )* Ok(()) @@ -199,3 +210,10 @@ macro_rules! remove_options { }; } apply_public_backends!(remove_options); + +fn is_enabled(backend: &str, config: &Config) -> bool { + !config + .disabled_backends + .iter() + .any(|x| x.to_lowercase() == backend.to_lowercase()) +} diff --git a/src/backends/arch.rs b/src/backends/arch.rs index 0d02644..670ccc2 100644 --- a/src/backends/arch.rs +++ b/src/backends/arch.rs @@ -8,9 +8,7 @@ use crate::cmd::{command_found, run_command, run_command_for_stdout}; use crate::prelude::*; #[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)] -pub struct Arch { - pub command: &'static str, -} +pub struct Arch; pub type ArchPackageId = String; @@ -37,16 +35,25 @@ pub struct ArchRemoveOptions {} impl Arch { pub fn query_installed_packages( &self, - _: &Config, + config: &Config, ) -> Result> { - if !command_found("pacman") { + if !command_found(&config.arch_package_manager) { return Ok(BTreeMap::new()); } - let explicit = - run_command_for_stdout(["pacman", "--query", "--explicit", "--quiet"], Perms::Same)?; - let dependency = - run_command_for_stdout(["pacman", "--query", "--deps", "--quiet"], Perms::Same)?; + let explicit = run_command_for_stdout( + [ + &config.arch_package_manager, + "--query", + "--explicit", + "--quiet", + ], + Perms::Same, + )?; + let dependency = run_command_for_stdout( + [&config.arch_package_manager, "--query", "--deps", "--quiet"], + Perms::Same, + )?; Ok(dependency .lines() @@ -63,10 +70,10 @@ impl Arch { &self, packages: &BTreeMap, no_confirm: bool, - _: &Config, + config: &Config, ) -> Result<()> { run_command( - [self.command, "--sync"] + [&config.arch_package_manager, "--sync"] .into_iter() .chain(Some("--no_confirm").filter(|_| no_confirm)) .chain(packages.keys().map(String::as_str)) @@ -80,15 +87,17 @@ impl Arch { pub fn modify_packages( &self, packages: &BTreeMap, - _: &Config, + config: &Config, ) -> Result<()> { run_command( - [self.command, "--database", "--asdeps"].into_iter().chain( - packages - .iter() - .filter(|(_, m)| m.make_implicit) - .map(|(p, _)| p.as_str()), - ), + [&config.arch_package_manager, "--database", "--asdeps"] + .into_iter() + .chain( + packages + .iter() + .filter(|(_, m)| m.make_implicit) + .map(|(p, _)| p.as_str()), + ), Perms::AsRoot, ) } @@ -100,9 +109,9 @@ impl Arch { config: &Config, ) -> Result<()> { run_command( - [self.command, "--remove", "--recursive"] + [&config.arch_package_manager, "--remove", "--recursive"] .into_iter() - .chain(config.aur_rm_args.iter().map(String::as_str)) + .chain(config.arch_rm_args.iter().map(String::as_str)) .chain(Some("--no_confirm").filter(|_| no_confirm)) .chain(packages.keys().map(String::as_str)), Perms::AsRoot, @@ -119,9 +128,7 @@ impl Arch { x.clone().try_into::()?.package, x.clone().try_into()?, )), - _ => Err(eyre!( - "pacman/yay/paru packages must be either a string or a table" - )), + _ => Err(eyre!("arch packages must be either a string or a table")), } } } diff --git a/src/backends/pacman.rs b/src/backends/pacman.rs deleted file mode 100644 index 6a79f0f..0000000 --- a/src/backends/pacman.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::prelude::*; -use color_eyre::Result; -use std::collections::BTreeMap; - -#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)] -pub struct Pacman; -impl Pacman { - const PACMAN: Arch = Arch { command: "pacman" }; -} - -impl Backend for Pacman { - type PackageId = ArchPackageId; - type QueryInfo = ArchQueryInfo; - type InstallOptions = ArchInstallOptions; - type ModificationOptions = ArchModificationOptions; - type RemoveOptions = ArchRemoveOptions; - - fn query_installed_packages( - config: &Config, - ) -> Result> { - Self::PACMAN.query_installed_packages(config) - } - fn install_packages( - packages: &BTreeMap, - no_confirm: bool, - config: &Config, - ) -> Result<()> { - Self::PACMAN.install_packages(packages, no_confirm, config) - } - fn modify_packages( - packages: &BTreeMap, - config: &Config, - ) -> Result<()> { - Self::PACMAN.modify_packages(packages, config) - } - fn remove_packages( - packages: &BTreeMap, - no_confirm: bool, - config: &Config, - ) -> Result<()> { - Self::PACMAN.remove_packages(packages, no_confirm, config) - } - fn try_parse_toml_package( - toml: &toml::Value, - ) -> Result<(Self::PackageId, Self::InstallOptions)> { - Self::PACMAN.try_parse_toml_package(toml) - } -} diff --git a/src/backends/paru.rs b/src/backends/paru.rs deleted file mode 100644 index 893353e..0000000 --- a/src/backends/paru.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::prelude::*; -use color_eyre::Result; -use std::collections::BTreeMap; - -#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)] -pub struct Paru; -impl Paru { - const PARU: Arch = Arch { command: "paru" }; -} - -impl Backend for Paru { - type PackageId = ArchPackageId; - type QueryInfo = ArchQueryInfo; - type InstallOptions = ArchInstallOptions; - type ModificationOptions = ArchModificationOptions; - type RemoveOptions = ArchRemoveOptions; - - fn query_installed_packages( - config: &Config, - ) -> Result> { - Self::PARU.query_installed_packages(config) - } - fn install_packages( - packages: &BTreeMap, - no_confirm: bool, - config: &Config, - ) -> Result<()> { - Self::PARU.install_packages(packages, no_confirm, config) - } - fn modify_packages( - packages: &BTreeMap, - config: &Config, - ) -> Result<()> { - Self::PARU.modify_packages(packages, config) - } - fn remove_packages( - packages: &BTreeMap, - no_confirm: bool, - config: &Config, - ) -> Result<()> { - Self::PARU.remove_packages(packages, no_confirm, config) - } - fn try_parse_toml_package( - toml: &toml::Value, - ) -> Result<(Self::PackageId, Self::InstallOptions)> { - Self::PARU.try_parse_toml_package(toml) - } -} diff --git a/src/backends/yay.rs b/src/backends/yay.rs deleted file mode 100644 index 106e946..0000000 --- a/src/backends/yay.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::prelude::*; -use color_eyre::Result; -use std::collections::BTreeMap; - -#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)] -pub struct Yay; -impl Yay { - const YAY: Arch = Arch { command: "yay" }; -} - -impl Backend for Yay { - type PackageId = ArchPackageId; - type QueryInfo = ArchQueryInfo; - type InstallOptions = ArchInstallOptions; - type ModificationOptions = ArchModificationOptions; - type RemoveOptions = ArchRemoveOptions; - - fn query_installed_packages( - config: &Config, - ) -> Result> { - Self::YAY.query_installed_packages(config) - } - fn install_packages( - packages: &BTreeMap, - no_confirm: bool, - config: &Config, - ) -> Result<()> { - Self::YAY.install_packages(packages, no_confirm, config) - } - fn modify_packages( - packages: &BTreeMap, - config: &Config, - ) -> Result<()> { - Self::YAY.modify_packages(packages, config) - } - fn remove_packages( - packages: &BTreeMap, - no_confirm: bool, - config: &Config, - ) -> Result<()> { - Self::YAY.remove_packages(packages, no_confirm, config) - } - fn try_parse_toml_package( - toml: &toml::Value, - ) -> Result<(Self::PackageId, Self::InstallOptions)> { - Self::YAY.try_parse_toml_package(toml) - } -} diff --git a/src/config.rs b/src/config.rs index 5d37a79..1a6bcfa 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,18 +9,24 @@ use serde::{Deserialize, Serialize}; #[serde_inline_default] #[derive(Debug, Serialize, Deserialize)] pub struct Config { - #[serde_inline_default(Config::default().aur_rm_args)] - pub aur_rm_args: Vec, + #[serde_inline_default(Config::default().arch_package_manager)] + pub arch_package_manager: String, + #[serde_inline_default(Config::default().arch_rm_args)] + pub arch_rm_args: Vec, #[serde_inline_default(Config::default().flatpak_systemwide)] pub flatpak_systemwide: bool, + #[serde_inline_default(Config::default().disabled_backends)] + pub disabled_backends: Vec, #[serde_inline_default(Config::default().hostname_groups)] pub hostname_groups: BTreeMap>, } impl Default for Config { fn default() -> Self { Config { - aur_rm_args: Vec::new(), + arch_package_manager: "pacman".to_string(), + arch_rm_args: Vec::new(), flatpak_systemwide: true, + disabled_backends: Vec::new(), hostname_groups: BTreeMap::new(), } } diff --git a/src/core.rs b/src/core.rs index d74f445..1587210 100644 --- a/src/core.rs +++ b/src/core.rs @@ -20,7 +20,7 @@ impl MainArguments { } else { dirs::config_dir() .map(|path| path.join("pacdef/")) - .context("getting the default pacdef config directory")? + .ok_or(eyre!("getting the default pacdef config directory"))? }; let config = Config::load(&config_dir).context("loading config file")?; @@ -58,7 +58,7 @@ impl CleanPackageAction { .default(true) .show_default(true) .interact() - .wrap_err(eyre!("getting user confirmation"))? + .wrap_err("getting user confirmation")? { return Ok(()); } @@ -93,7 +93,7 @@ impl SyncPackageAction { .default(true) .show_default(true) .interact() - .wrap_err(eyre!("getting user confirmation"))? + .wrap_err("getting user confirmation")? { return Ok(()); } diff --git a/src/groups.rs b/src/groups.rs index 9984468..8970867 100644 --- a/src/groups.rs +++ b/src/groups.rs @@ -1,10 +1,9 @@ use crate::prelude::*; use color_eyre::{ - eyre::{eyre, Context}, + eyre::{eyre, Context, ContextCompat}, Result, }; use toml::{Table, Value}; -use walkdir::{DirEntry, WalkDir}; use std::{collections::BTreeMap, fs::read_to_string, path::Path}; @@ -35,28 +34,23 @@ impl Groups { )); } - let group_files: Vec = WalkDir::new(&group_dir) - .follow_links(true) - .into_iter() - .collect::>()?; - - for group_file in group_files.iter().filter(|path| path.path().is_file()) { - let group_name = group_file - .path() - .strip_prefix(&group_dir)? - .to_str() - .ok_or(eyre!("will not fail on linux"))? - .to_string(); + for group_name in config.hostname_groups.get(hostname).wrap_err(format!( + "no hostname entry in hostname_groups config for the hostname: {hostname}" + ))? { + let mut group_file = group_dir.join(group_name); + group_file.set_extension("toml"); log::info!("parsing group file: {group_name}@{group_file:?}"); - let file_contents = read_to_string(group_file.path()).wrap_err("reading group file")?; + let file_contents = read_to_string(&group_file) + .wrap_err(format!("reading group file {group_name}@{group_file:?}"))?; - let install_options: InstallOptions = - parse_group_file(&group_name, &file_contents).wrap_err("parsing group file")?; + let install_options: InstallOptions = parse_group_file(group_name, &file_contents) + .wrap_err(format!("parsing group file {group_name}@{group_file:?}"))?; - groups.insert(group_name, install_options); + groups.insert(group_name.clone(), install_options); } + Ok(groups) } } diff --git a/src/main.rs b/src/main.rs index 72d21db..6e8b4ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,11 +14,8 @@ missing_docs )] -use color_eyre::{ - eyre::{eyre, Context}, - Result, -}; use clap::Parser; +use color_eyre::Result; use pacdef::MainArguments; fn main() -> Result<()> {