lib.rs
1 //! Update system for AC/DC. 2 //! 3 //! This crate handles updates for AC/DC itself and installed components: 4 //! - Self-update functionality for the ac-dc binary 5 //! - Component updates (ADNet, ADL, SDK) 6 //! - Version checking 7 //! - Rollback support 8 9 use acdc_core::Result; 10 use serde::{Deserialize, Serialize}; 11 12 pub mod components; 13 pub mod rollback; 14 pub mod self_update; 15 pub mod version; 16 17 pub use version::VersionInfo; 18 19 /// Check for available updates. 20 pub async fn check() -> Result<UpdateInfo> { 21 let current_version = env!("CARGO_PKG_VERSION").to_string(); 22 23 // Check for self-update 24 let latest_version = self_update::check_version().await.ok().flatten(); 25 let update_available = latest_version 26 .as_ref() 27 .map(|v| v != ¤t_version) 28 .unwrap_or(false); 29 30 // Check for component updates 31 let component_updates = components::check().await.unwrap_or_default(); 32 33 Ok(UpdateInfo { 34 current_version, 35 latest_version, 36 update_available, 37 component_updates, 38 }) 39 } 40 41 /// Update AC/DC itself. 42 pub async fn update_self(force: bool) -> Result<()> { 43 self_update::update(force).await 44 } 45 46 /// Update installed components. 47 pub async fn update_components(component: Option<&str>) -> Result<()> { 48 if let Some(name) = component { 49 components::update(name).await 50 } else { 51 components::update_all().await 52 } 53 } 54 55 /// Rollback to previous version. 56 pub async fn rollback() -> Result<()> { 57 rollback::rollback().await 58 } 59 60 /// Information about available updates. 61 #[derive(Debug, Clone, Serialize, Deserialize)] 62 pub struct UpdateInfo { 63 /// Current AC/DC version 64 pub current_version: String, 65 /// Latest available version 66 pub latest_version: Option<String>, 67 /// Whether an update is available 68 pub update_available: bool, 69 /// Component updates available 70 pub component_updates: Vec<ComponentUpdate>, 71 } 72 73 impl UpdateInfo { 74 /// Format update info for display. 75 pub fn format(&self) -> String { 76 let mut output = String::new(); 77 78 output.push_str("Update Status\n"); 79 output.push_str("═════════════\n\n"); 80 81 output.push_str(&format!("AC/DC Version: {}\n", self.current_version)); 82 83 if let Some(ref latest) = self.latest_version { 84 if self.update_available { 85 output.push_str(&format!("Latest Version: {} (update available!)\n", latest)); 86 } else { 87 output.push_str(&format!("Latest Version: {} (up to date)\n", latest)); 88 } 89 } else { 90 output.push_str("Latest Version: Unable to check\n"); 91 } 92 93 if !self.component_updates.is_empty() { 94 output.push_str("\nComponent Updates Available:\n"); 95 for update in &self.component_updates { 96 output.push_str(&format!( 97 " {} {} → {}\n", 98 update.name, update.current, update.latest 99 )); 100 } 101 } else { 102 output.push_str("\nAll components are up to date.\n"); 103 } 104 105 output 106 } 107 } 108 109 /// Information about a component update. 110 #[derive(Debug, Clone, Serialize, Deserialize)] 111 pub struct ComponentUpdate { 112 /// Component name 113 pub name: String, 114 /// Current version 115 pub current: String, 116 /// Latest version 117 pub latest: String, 118 }