/ cli / src / helpers / updater.rs
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(&current_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  }