use std::collections::HashSet;
use std::hash::BuildHasher;
use std::process::{Command, Stdio};
pub fn get_upgradable_packages() -> HashSet<String> {
tracing::debug!("Running: pacman -Qu");
let output = Command::new("pacman")
.args(["-Qu"])
.env("LC_ALL", "C")
.env("LANG", "C")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output();
match output {
Ok(output) => {
if output.status.success() {
let text = String::from_utf8_lossy(&output.stdout);
let packages: HashSet<String> = text
.lines()
.filter_map(|line| {
let line = line.trim();
if line.is_empty() {
return None;
}
Some(line.find(' ').map_or_else(
|| line.to_string(),
|space_pos| line[..space_pos].trim().to_string(),
))
})
.collect();
tracing::debug!(
"Successfully retrieved {} upgradable packages",
packages.len()
);
packages
} else {
HashSet::new()
}
}
Err(e) => {
tracing::debug!("Failed to execute pacman -Qu: {} (assuming no upgrades)", e);
HashSet::new()
}
}
}
pub fn get_installed_packages() -> HashSet<String> {
tracing::debug!("Running: pacman -Qq");
let output = Command::new("pacman")
.args(["-Qq"])
.env("LC_ALL", "C")
.env("LANG", "C")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output();
match output {
Ok(output) => {
if output.status.success() {
let text = String::from_utf8_lossy(&output.stdout);
let packages: HashSet<String> =
text.lines().map(|s| s.trim().to_string()).collect();
tracing::debug!(
"Successfully retrieved {} installed packages",
packages.len()
);
packages
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
tracing::error!(
"pacman -Qq failed with status {:?}: {}",
output.status.code(),
stderr
);
HashSet::new()
}
}
Err(e) => {
tracing::error!("Failed to execute pacman -Qq: {}", e);
HashSet::new()
}
}
}
fn check_if_provided<S: BuildHasher + Default>(
name: &str,
_installed: &HashSet<String, S>,
) -> Option<String> {
let output = Command::new("pacman")
.args(["-Qqo", name])
.env("LC_ALL", "C")
.env("LANG", "C")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output();
match output {
Ok(output) if output.status.success() => {
let text = String::from_utf8_lossy(&output.stdout);
let providing_pkg = text.lines().next().map(|s| s.trim().to_string());
if let Some(providing_pkg) = &providing_pkg {
tracing::debug!("{} is provided by {}", name, providing_pkg);
}
providing_pkg
}
_ => None,
}
}
#[must_use]
pub fn get_provided_packages<S: BuildHasher + Default>(
_installed: &HashSet<String, S>,
) -> HashSet<String> {
HashSet::new()
}
#[must_use]
pub fn is_package_installed_or_provided<S: BuildHasher + Default>(
name: &str,
installed: &HashSet<String, S>,
_provided: &HashSet<String, S>,
) -> bool {
if installed.contains(name) {
return true;
}
check_if_provided(name, installed).is_some()
}