1use crate::manager::{PackageError, PackageManager, RunOutcome, Runner};
4
5pub struct Dnf;
7
8impl PackageManager for Dnf {
9 fn name(&self) -> &'static str {
10 "dnf"
11 }
12
13 fn is_available(&self) -> bool {
14 which::which("dnf").is_ok()
15 }
16
17 fn exists(&self, runner: &dyn Runner, pkg: &str) -> Result<bool, PackageError> {
22 if let Some(group) = pkg.strip_prefix('@') {
23 let RunOutcome { status, .. } = runner.run("dnf", &["group", "info", group])?;
24 return Ok(status == 0);
25 }
26 let RunOutcome { status, stdout, .. } =
27 runner.run("dnf", &["repoquery", "--quiet", "--whatprovides", pkg])?;
28 Ok(status == 0 && !stdout.trim().is_empty())
29 }
30
31 fn is_installed(&self, runner: &dyn Runner, pkg: &str) -> Result<bool, PackageError> {
34 let RunOutcome { status, .. } = runner.run("rpm", &["-q", "--whatprovides", pkg])?;
35 Ok(status == 0)
36 }
37
38 fn install(&self, runner: &dyn Runner, packages: &[String]) -> Result<(), PackageError> {
39 let mut args = vec!["install", "-y"];
40 args.extend(packages.iter().map(String::as_str));
41 let RunOutcome { status, stderr, .. } = runner.run_as_root("dnf", &args)?;
42 if status != 0 {
43 return Err(PackageError::ExitFailure { status, stderr });
44 }
45 Ok(())
46 }
47}