updater.rs
1 // Copyright (c) 2025-2026 ACDC Network 2 // This file is part of the alphaos library. 3 // 4 // Alpha Chain | Delta Chain Protocol 5 // International Monetary Graphite. 6 // 7 // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com). 8 // They built world-class ZK infrastructure. We installed the EASY button. 9 // Their cryptography: elegant. Our modifications: bureaucracy-compatible. 10 // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours. 11 // 12 // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0 13 // All modifications and new work: CC0 1.0 Universal Public Domain Dedication. 14 // No rights reserved. No permission required. No warranty. No refunds. 15 // 16 // https://creativecommons.org/publicdomain/zero/1.0/ 17 // SPDX-License-Identifier: CC0-1.0 18 19 use colored::Colorize; 20 use self_update::{backends::github, version::bump_is_greater, Status}; 21 use std::fmt::Write; 22 23 pub struct Updater; 24 25 impl Updater { 26 const ALPHAOS_BIN_NAME: &'static str = "alphaos"; 27 const ALPHAOS_REPO_NAME: &'static str = "alphaos"; 28 const ALPHAOS_REPO_OWNER: &'static str = "ProvableHQ"; 29 30 /// Show all available releases for `alphaos`. 31 pub fn show_available_releases() -> Result<String, UpdaterError> { 32 let releases = github::ReleaseList::configure() 33 .repo_owner(Self::ALPHAOS_REPO_OWNER) 34 .repo_name(Self::ALPHAOS_REPO_NAME) 35 .build()? 36 .fetch()?; 37 38 let mut output = "List of available versions\n".to_string(); 39 for release in releases { 40 let _ = writeln!(output, " * {}", release.version); 41 } 42 Ok(output) 43 } 44 45 /// Update `alphaos` to the specified release. 46 pub fn update_to_release(show_output: bool, version: Option<String>) -> Result<Status, UpdaterError> { 47 let mut update_builder = github::Update::configure(); 48 49 update_builder 50 .repo_owner(Self::ALPHAOS_REPO_OWNER) 51 .repo_name(Self::ALPHAOS_REPO_NAME) 52 .bin_name(Self::ALPHAOS_BIN_NAME) 53 .current_version(env!("CARGO_PKG_VERSION")) 54 .show_download_progress(show_output) 55 .no_confirm(true) 56 .show_output(show_output); 57 58 let status = match version { 59 None => update_builder.build()?.update()?, 60 Some(v) => update_builder.target_version_tag(&v).build()?.update()?, 61 }; 62 63 Ok(status) 64 } 65 66 /// Check if there is an available update for `alphaos` and return the newest release. 67 pub fn update_available() -> Result<String, UpdaterError> { 68 let updater = github::Update::configure() 69 .repo_owner(Self::ALPHAOS_REPO_OWNER) 70 .repo_name(Self::ALPHAOS_REPO_NAME) 71 .bin_name(Self::ALPHAOS_BIN_NAME) 72 .current_version(env!("CARGO_PKG_VERSION")) 73 .build()?; 74 75 let current_version = updater.current_version(); 76 let latest_release = updater.get_latest_release()?; 77 78 if bump_is_greater(¤t_version, &latest_release.version)? { 79 Ok(latest_release.version) 80 } else { 81 Err(UpdaterError::OldReleaseVersion(current_version, latest_release.version)) 82 } 83 } 84 85 /// Returns the message to be printed to the CLI (if any). 86 pub fn print_cli() -> Option<String> { 87 if let Ok(latest_version) = Self::update_available() { 88 let mut output = "🟢 A new version is available! Run".bold().green().to_string(); 89 output += &" `alphaos update` ".bold().white(); 90 output += &format!("to update to v{latest_version}.").bold().green(); 91 Some(output) 92 } else { 93 None 94 } 95 } 96 } 97 98 #[derive(Debug, Error)] 99 pub enum UpdaterError { 100 #[error("{}: {}", _0, _1)] 101 Crate(&'static str, String), 102 103 #[error("The current version {} is more recent than the release version {}", _0, _1)] 104 OldReleaseVersion(String, String), 105 } 106 107 impl From<self_update::errors::Error> for UpdaterError { 108 fn from(error: self_update::errors::Error) -> Self { 109 UpdaterError::Crate("self_update", error.to_string()) 110 } 111 }