Skip to main content

krypt_pkg/
pacman.rs

1//! `pacman` / `paru` package manager implementation (Arch Linux).
2//!
3//! Prefers `paru` if available (adds AUR support), falls back to `pacman`.
4//! Both use the same install syntax. The manager name is always `"pacman"` to
5//! match the `DepsGroup.pacman` config field.
6
7use crate::manager::{PackageError, PackageManager, RunOutcome, Runner};
8
9/// Package manager implementation for Arch Linux (pacman / paru).
10pub struct Pacman;
11
12impl Pacman {
13    /// Binary to use for installation: `paru` if available, else `pacman`.
14    fn binary(&self) -> &'static str {
15        if which::which("paru").is_ok() {
16            "paru"
17        } else {
18            "pacman"
19        }
20    }
21}
22
23impl PackageManager for Pacman {
24    fn name(&self) -> &'static str {
25        "pacman"
26    }
27
28    fn is_available(&self) -> bool {
29        which::which("pacman").is_ok()
30    }
31
32    fn is_installed(&self, runner: &dyn Runner, pkg: &str) -> Result<bool, PackageError> {
33        let RunOutcome { status, .. } = runner.run("pacman", &["-Q", pkg])?;
34        match status {
35            0 => Ok(true),
36            _ => Ok(false),
37        }
38    }
39
40    fn install(&self, runner: &dyn Runner, packages: &[String]) -> Result<(), PackageError> {
41        let bin = self.binary();
42        let mut args = vec![bin, "-S", "--noconfirm"];
43        let pkg_refs: Vec<&str> = packages.iter().map(String::as_str).collect();
44        args.extend_from_slice(&pkg_refs);
45        let RunOutcome { status, stderr, .. } = runner.run("sudo", &args)?;
46        if status != 0 {
47            return Err(PackageError::ExitFailure { status, stderr });
48        }
49        Ok(())
50    }
51}