horto_os_ui_shared/kits/
apt.rs1use crate::context::HostContext;
4use crate::error::{HortoError, Result};
5use std::process::Command;
6
7pub fn apt_update(ctx: &mut HostContext) -> Result<()> {
15 run_apt(ctx, &["update"])
16}
17
18pub fn apt_install(ctx: &mut HostContext, packages: &[&str]) -> Result<()> {
26 let mut args = vec!["install", "-y"];
27 args.extend_from_slice(packages);
28 run_apt(ctx, &args)
29}
30
31fn run_apt(ctx: &mut HostContext, args: &[&str]) -> Result<()> {
32 let summary = format!("apt {}", args.join(" "));
33 if ctx.is_dry_run() {
34 ctx.plan_action(summary);
35 return Ok(());
36 }
37 ctx.log(&summary);
38 let status = Command::new("apt")
39 .args(args)
40 .status()
41 .map_err(|e| HortoError::command("apt", e.to_string()))?;
42 if !status.success() {
43 return Err(HortoError::command(
44 "apt",
45 format!("{} -> {status}", args.join(" ")),
46 ));
47 }
48 Ok(())
49}
50
51#[must_use]
53pub fn package_installed(name: &str) -> bool {
54 Command::new("dpkg-query")
55 .args(["-W", "-f=${Status}", name])
56 .output()
57 .is_ok_and(|o| {
58 let s = String::from_utf8_lossy(&o.stdout);
59 s.contains("install ok installed")
60 })
61}