@@ -92,6 +92,7 @@ Pull requests for additional backends are welcome!
|
|||||||
| Python | `pip` | `[python]` | built-in | |
|
| Python | `pip` | `[python]` | built-in | |
|
||||||
| Rust | `cargo` | `[rust]` | built-in | |
|
| Rust | `cargo` | `[rust]` | built-in | |
|
||||||
| Rustup | `rustup` | `[rustup]` | built-in | See the comments [below](#rustup) about the syntax of the packages in the group file. |
|
| Rustup | `rustup` | `[rustup]` | built-in | See the comments [below](#rustup) about the syntax of the packages in the group file. |
|
||||||
|
| Void Linux | `xbps` | `[void]` | built-in | |
|
||||||
|
|
||||||
Backends that have a `feature flag` require setting the respective flag for the build process.
|
Backends that have a `feature flag` require setting the respective flag for the build process.
|
||||||
The appropriate system libraries and their header files must be present on the machine and be detectable by `pkg-config`.
|
The appropriate system libraries and their header files must be present on the machine and be detectable by `pkg-config`.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ path-absolutize = "3.1"
|
|||||||
regex = { version = "1.10", default-features = false, features = ["std"] }
|
regex = { version = "1.10", default-features = false, features = ["std"] }
|
||||||
termios = "0.3"
|
termios = "0.3"
|
||||||
walkdir = "2.5"
|
walkdir = "2.5"
|
||||||
|
libc = "0.2"
|
||||||
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
@@ -29,12 +30,10 @@ pacdef_macros = { path = "../pacdef_macros", version = "1.0" }
|
|||||||
alpm = { version = "3.0", optional = true }
|
alpm = { version = "3.0", optional = true }
|
||||||
rust-apt = { version = "0.7", optional = true }
|
rust-apt = { version = "0.7", optional = true }
|
||||||
|
|
||||||
libc = { version = "0.2", optional = true } # for debian
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rstest = "0.18"
|
rstest = "0.18"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
arch = ["dep:alpm"]
|
arch = ["dep:alpm"]
|
||||||
debian = ["dep:rust-apt", "dep:libc"]
|
debian = ["dep:rust-apt"]
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::process::Command;
|
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
@@ -8,6 +7,7 @@ use rust_apt::new_cache;
|
|||||||
|
|
||||||
use crate::backend::backend_trait::{Backend, Switches, Text};
|
use crate::backend::backend_trait::{Backend, Switches, Text};
|
||||||
use crate::backend::macros::impl_backend_constants;
|
use crate::backend::macros::impl_backend_constants;
|
||||||
|
use crate::backend::root::build_base_command_with_privileges;
|
||||||
use crate::{Group, Package};
|
use crate::{Group, Package};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -104,19 +104,3 @@ impl Debian {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn we_are_root() -> bool {
|
|
||||||
let uid = unsafe { libc::geteuid() };
|
|
||||||
uid == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_base_command_with_privileges(binary: &str) -> Command {
|
|
||||||
let cmd = if we_are_root() {
|
|
||||||
Command::new(binary)
|
|
||||||
} else {
|
|
||||||
let mut cmd = Command::new("sudo");
|
|
||||||
cmd.arg(binary);
|
|
||||||
cmd
|
|
||||||
};
|
|
||||||
cmd
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ pub mod flatpak;
|
|||||||
pub mod python;
|
pub mod python;
|
||||||
pub mod rust;
|
pub mod rust;
|
||||||
pub mod rustup;
|
pub mod rustup;
|
||||||
|
pub mod void;
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
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::backend::root::build_base_command_with_privileges;
|
||||||
|
use crate::{Group, Package};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Void {
|
||||||
|
pub(crate) packages: HashSet<Package>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = &[];
|
||||||
|
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 Backend for Void {
|
||||||
|
impl_backend_constants!();
|
||||||
|
|
||||||
|
fn get_all_installed_packages(&self) -> Result<HashSet<Package>> {
|
||||||
|
// Removes the package status and description from output
|
||||||
|
let re_str_1 = r"^ii |^uu |^hr |^\?\? | .*";
|
||||||
|
// Removes the package version from output
|
||||||
|
let re_str_2 = r"-[^-]*$";
|
||||||
|
let re1 = Regex::new(re_str_1)?;
|
||||||
|
let re2 = Regex::new(re_str_2)?;
|
||||||
|
let mut cmd = Command::new(QUERY_BINARY);
|
||||||
|
cmd.args(["-l"]);
|
||||||
|
let output = String::from_utf8(cmd.output()?.stdout)?;
|
||||||
|
|
||||||
|
let packages = output
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
let result = re1.replace_all(line, "");
|
||||||
|
let result = re2.replace_all(&result, "");
|
||||||
|
result.to_string().into()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Ok(packages)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_explicitly_installed_packages(&self) -> Result<HashSet<Package>> {
|
||||||
|
// Removes the package version from output
|
||||||
|
let re_str = r"-[^-]*$";
|
||||||
|
let re = Regex::new(re_str)?;
|
||||||
|
let mut cmd = Command::new(QUERY_BINARY);
|
||||||
|
cmd.args(["-m"]);
|
||||||
|
let output = String::from_utf8(cmd.output()?.stdout)?;
|
||||||
|
|
||||||
|
let packages = 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<ExitStatus> {
|
||||||
|
let mut cmd = build_base_command_with_privileges(INSTALL_BINARY);
|
||||||
|
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<ExitStatus> {
|
||||||
|
let mut cmd = build_base_command_with_privileges(REMOVE_BINARY);
|
||||||
|
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<ExitStatus> {
|
||||||
|
let mut cmd = build_base_command_with_privileges(PKGDB_BINARY);
|
||||||
|
cmd.args(self.get_switches_make_dependency());
|
||||||
|
|
||||||
|
for p in packages {
|
||||||
|
cmd.arg(format!("{p}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.status()
|
||||||
|
.with_context(|| format!("running command [{cmd:?}]"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Show information from package manager for package.
|
||||||
|
fn show_package_info(&self, package: &Package) -> Result<ExitStatus> {
|
||||||
|
let mut cmd = Command::new(QUERY_BINARY);
|
||||||
|
cmd.args(self.get_switches_info());
|
||||||
|
cmd.arg(format!("{package}"));
|
||||||
|
cmd.status()
|
||||||
|
.with_context(|| format!("running command {cmd:?}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Void {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
packages: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ mod actual;
|
|||||||
mod backend_trait;
|
mod backend_trait;
|
||||||
mod iter;
|
mod iter;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
mod root;
|
||||||
mod todo_per_backend;
|
mod todo_per_backend;
|
||||||
|
|
||||||
pub use backend_trait::Backend;
|
pub use backend_trait::Backend;
|
||||||
@@ -20,4 +21,5 @@ pub enum Backends {
|
|||||||
Python,
|
Python,
|
||||||
Rust,
|
Rust,
|
||||||
Rustup,
|
Rustup,
|
||||||
|
Void,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
pub fn we_are_root() -> bool {
|
||||||
|
let uid = unsafe { libc::geteuid() };
|
||||||
|
uid == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_base_command_with_privileges(binary: &str) -> Command {
|
||||||
|
let cmd = if we_are_root() {
|
||||||
|
Command::new(binary)
|
||||||
|
} else {
|
||||||
|
let mut cmd = Command::new("sudo");
|
||||||
|
cmd.arg(binary);
|
||||||
|
cmd
|
||||||
|
};
|
||||||
|
cmd
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user