use zbus::{Connection, Proxy}; use std::error::Error; /// Daemon client for communicating with apt-ostreed pub struct DaemonClient { connection: Connection, proxy: Proxy<'static>, } impl DaemonClient { /// Create a new daemon client pub async fn new() -> Result> { let connection = Connection::system().await?; let proxy = Proxy::new( &connection, "org.aptostree.dev", "/org/aptostree/dev/Daemon", "org.aptostree.dev.Daemon" ).await?; Ok(Self { connection, proxy }) } /// Ping the daemon pub async fn ping(&self) -> Result> { let reply: String = self.proxy.call("Ping", &()).await?; Ok(reply) } /// Get system status pub async fn status(&self) -> Result> { let reply: String = self.proxy.call("Status", &()).await?; Ok(reply) } /// Install packages pub async fn install_packages(&self, packages: Vec, yes: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("InstallPackages", &(packages, yes, dry_run)).await?; Ok(reply) } /// Remove packages pub async fn remove_packages(&self, packages: Vec, yes: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("RemovePackages", &(packages, yes, dry_run)).await?; Ok(reply) } /// Upgrade system pub async fn upgrade_system(&self, yes: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("UpgradeSystem", &(yes, dry_run)).await?; Ok(reply) } /// Rollback system pub async fn rollback(&self, yes: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("Rollback", &(yes, dry_run)).await?; Ok(reply) } /// List packages pub async fn list_packages(&self) -> Result> { let reply: String = self.proxy.call("ListPackages", &()).await?; Ok(reply) } /// Search packages pub async fn search_packages(&self, query: String, verbose: bool) -> Result> { let reply: String = self.proxy.call("SearchPackages", &(query, verbose)).await?; Ok(reply) } /// Show package info pub async fn show_package_info(&self, package: String) -> Result> { let reply: String = self.proxy.call("ShowPackageInfo", &(package)).await?; Ok(reply) } /// Show history pub async fn show_history(&self, verbose: bool, limit: u32) -> Result> { let reply: String = self.proxy.call("ShowHistory", &(verbose, limit)).await?; Ok(reply) } /// Checkout to different branch/commit pub async fn checkout(&self, target: String, yes: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("Checkout", &(target, yes, dry_run)).await?; Ok(reply) } /// Prune deployments pub async fn prune_deployments(&self, keep: u32, yes: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("PruneDeployments", &(keep, yes, dry_run)).await?; Ok(reply) } /// Initialize system pub async fn initialize(&self, branch: String) -> Result> { let reply: String = self.proxy.call("Initialize", &(branch)).await?; Ok(reply) } /// Deploy a specific commit pub async fn deploy(&self, commit: String, reboot: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("Deploy", &(commit, reboot, dry_run)).await?; Ok(reply) } /// Enhanced rollback with OSTree integration pub async fn rollback_enhanced(&self, reboot: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("RollbackEnhanced", &(reboot, dry_run)).await?; Ok(reply) } /// Enhanced upgrade with OSTree integration pub async fn upgrade_enhanced(&self, reboot: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("UpgradeEnhanced", &(reboot, dry_run)).await?; Ok(reply) } /// Reset to base deployment pub async fn reset(&self, reboot: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("Reset", &(reboot, dry_run)).await?; Ok(reply) } /// Rebase to different tree pub async fn rebase(&self, refspec: String, reboot: bool, allow_downgrade: bool, skip_purge: bool, dry_run: bool) -> Result> { let reply: String = self.proxy.call("Rebase", &(refspec, reboot, allow_downgrade, skip_purge, dry_run)).await?; Ok(reply) } /// Reload configuration pub async fn reload_configuration(&self) -> Result> { let reply: String = self.proxy.call("ReloadConfiguration", &()).await?; Ok(reply) } } /// Helper function to call daemon with fallback to client pub async fn call_daemon_with_fallback( daemon_call: F, client_fallback: T, ) -> Result> where F: FnOnce(&DaemonClient) -> std::pin::Pin>> + Send>>, T: FnOnce() -> std::pin::Pin>> + Send>>, { match DaemonClient::new().await { Ok(client) => { match daemon_call(&client).await { Ok(result) => Ok(result), Err(e) => { eprintln!("Warning: Daemon call failed: {}. Falling back to client...", e); client_fallback().await } } } Err(e) => { eprintln!("Warning: Could not connect to daemon: {}. Falling back to client...", e); client_fallback().await } } }