diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ccfdd49 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "rust-analyzer.linkedProjects": [ + "./crates/pacdef_core/Cargo.toml", + "./crates/pacdef_core/Cargo.toml", + "./crates/pacdef_core/Cargo.toml" + ] +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index d265fbd..54a24f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,3 +33,4 @@ strip = true default = [] debian = ["pacdef_core/debian"] arch = ["pacdef_core/arch"] +void = ["pacdef_core/void"] diff --git a/crates/pacdef_core/Cargo.toml b/crates/pacdef_core/Cargo.toml index 802d8fa..79fff2a 100644 --- a/crates/pacdef_core/Cargo.toml +++ b/crates/pacdef_core/Cargo.toml @@ -38,3 +38,4 @@ rstest = "0.18" default = [] arch = ["dep:alpm"] debian = ["dep:rust-apt", "dep:libc"] +void = [] diff --git a/crates/pacdef_core/src/backend/actual/mod.rs b/crates/pacdef_core/src/backend/actual/mod.rs index 36ad67e..07b1c59 100644 --- a/crates/pacdef_core/src/backend/actual/mod.rs +++ b/crates/pacdef_core/src/backend/actual/mod.rs @@ -2,6 +2,8 @@ pub mod arch; #[cfg(feature = "debian")] pub mod debian; +#[cfg(feature = "void")] +pub mod void; pub mod flatpak; pub mod python; pub mod rust; diff --git a/crates/pacdef_core/src/backend/actual/void.rs b/crates/pacdef_core/src/backend/actual/void.rs new file mode 100644 index 0000000..abc6f92 --- /dev/null +++ b/crates/pacdef_core/src/backend/actual/void.rs @@ -0,0 +1,144 @@ +use core::panic; +use std::collections::HashSet; +use std::process::{Command, ExitStatus}; + +use anyhow::{Context, Result}; +use regex::Regex; + +use crate::backend::backend_trait::{Backend, Switches, Text}; +use crate::backend::macros::impl_backend_constants; +use crate::{Group, Package}; + +#[derive(Debug, Clone)] +pub struct Void { + pub(crate) packages: HashSet, +} + +const BINARY: Text = "xbps-install"; +const INSTALL_BINARY: Text = "xbps-install"; +const REMOVE_BINARY: Text = "xbps-remove"; +const QUERY_BINARY: Text = "xbps-query"; +const PKGDB_BINARY: Text = "xbps-pkgdb"; +const SECTION: Text = "void"; + +const SWITCHES_INFO: Switches = &["-m"]; +const SWITCHES_INSTALL: Switches = &["-S"]; +const SWITCHES_MAKE_DEPENDENCY: Switches = &["-m", "auto"]; +const SWITCHES_NOCONFIRM: Switches = &["-y"]; +const SWITCHES_REMOVE: Switches = &["-R"]; + +const SUPPORTS_AS_DEPENDENCY: bool = true; +impl Void { + fn get_binary_info(&self) -> Text { + QUERY_BINARY + } + + fn get_binary_install(&self) -> Text { + INSTALL_BINARY + } + + fn get_binary_remove(&self) -> Text { + REMOVE_BINARY + } + + fn get_binary_make_dependency(&self) -> Text { + PKGDB_BINARY + } +} + +impl Backend for Void { + impl_backend_constants!(); + + fn get_all_installed_packages(&self) -> Result> { + let re_str_1 = r"ii | .*"; + let re_str_2 = r"-[^-]*$"; + let re1 = Regex::new(re_str_1)?; + let re2 = Regex::new(re_str_2)?; + let mut cmd = Command::new(self.get_binary_info()); + cmd.args(&["-l"]); + let output = String::from_utf8(cmd.output()?.stdout)?; + + let packages: HashSet = output + .lines() + .map(|line| { + let result = re1.replace_all(line, "").to_string(); + let result = re2.replace_all(&result, "").to_string(); + result.into() + }) + .collect(); + Ok(packages) + } + + fn get_explicitly_installed_packages(&self) -> Result> { + let re_str = r"-[^-]*$"; + let re = Regex::new(re_str)?; + let mut cmd = Command::new(self.get_binary_info()); + cmd.args(self.get_switches_info()); + let output = String::from_utf8(cmd.output()?.stdout)?; + + let packages: HashSet = output + .lines() + .map(|line| { + let result = re.replace_all(line, "").to_string(); + result.into() + }) + .collect(); + Ok(packages) + } + + /// Install the specified packages. + fn install_packages(&self, packages: &[Package], noconfirm: bool) -> Result { + let mut cmd = Command::new("sudo"); + cmd.arg(self.get_binary_install()); + cmd.args(self.get_switches_install()); + + if noconfirm { + cmd.args(self.get_switches_noconfirm()); + } + + for p in packages { + cmd.arg(format!("{p}")); + } + + cmd.status() + .with_context(|| format!("running command {cmd:?}")) + } + + fn remove_packages(&self, packages: &[Package], noconfirm: bool) -> Result { + let mut cmd = Command::new("sudo"); + cmd.arg(self.get_binary_remove()); + cmd.args(self.get_switches_remove()); + + if noconfirm { + cmd.args(self.get_switches_noconfirm()); + } + + for p in packages { + cmd.arg(format!("{p}")); + } + + cmd.status() + .with_context(|| format!("running command [{cmd:?}]")) + } + + fn make_dependency(&self, packages: &[Package]) -> Result { + let mut cmd = Command::new("sudo"); + cmd.arg(self.get_binary_make_dependency()); + cmd.args(self.get_switches_make_dependency()); + + for p in packages { + cmd.arg(format!("{p}")); + } + + cmd.status() + .with_context(|| format!("running command [{cmd:?}]")) + } +} + +impl Void { + pub fn new() -> Self { + Void { + packages: HashSet::new(), + } + } +} diff --git a/crates/pacdef_core/src/backend/mod.rs b/crates/pacdef_core/src/backend/mod.rs index 0664d7e..30215ac 100644 --- a/crates/pacdef_core/src/backend/mod.rs +++ b/crates/pacdef_core/src/backend/mod.rs @@ -16,6 +16,8 @@ pub enum Backends { Arch, #[cfg(feature = "debian")] Debian, + #[cfg(feature = "void")] + Void, Flatpak, Python, Rust,