feat(void): add void Linux backend

PR #69
This commit is contained in:
steven-omaha
2024-04-05 08:53:34 +02:00
committed by GitHub
7 changed files with 160 additions and 20 deletions
@@ -1,5 +1,4 @@
use std::collections::HashSet;
use std::process::Command;
use std::process::ExitStatus;
use anyhow::{Context, Result};
@@ -8,6 +7,7 @@ use rust_apt::new_cache;
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)]
@@ -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 rust;
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
View File
@@ -2,6 +2,7 @@ mod actual;
mod backend_trait;
mod iter;
mod macros;
mod root;
mod todo_per_backend;
pub use backend_trait::Backend;
@@ -20,4 +21,5 @@ pub enum Backends {
Python,
Rust,
Rustup,
Void,
}
+17
View File
@@ -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
}