use anyhow::Result; use tracing::info; use crate::Router; impl Router { /// Verify opkg is available, returning a clear error if not. pub fn opkg_check(&self) -> Result<()> { let (_, code) = self.run("test -x /usr/bin/opkg")?; if code != 0 { anyhow::bail!( "opkg not found at /usr/bin/opkg — this router's firmware may not \ support package management (TollGate requires a standard OpenWrt build)" ); } Ok(()) } /// `opkg update` — refresh package lists. pub fn opkg_update(&self) -> Result<()> { info!("[{}] opkg update", self.host); self.run_ok("/usr/bin/opkg update")?; Ok(()) } /// Install a package, skipping if already installed. pub fn opkg_install(&self, package: &str) -> Result<()> { // Check if already installed to avoid unnecessary network traffic. let (_, code) = self.run(&format!("/usr/bin/opkg list-installed | grep -q '^{} '", package))?; if code == 0 { info!("[{}] {} already installed", self.host, package); return Ok(()); } info!("[{}] opkg install {}", self.host, package); self.run_ok(&format!("/usr/bin/opkg install {}", package))?; Ok(()) } /// Remove a package. pub fn opkg_remove(&self, package: &str) -> Result<()> { info!("[{}] opkg remove {}", self.host, package); self.run_ok(&format!("/usr/bin/opkg remove {}", package))?; Ok(()) } }