snarkos_cli/helpers/
updater.rs1use colored::Colorize;
17use self_update::{Status, backends::github, version::bump_is_greater};
18use std::fmt::Write;
19
20pub struct Updater;
21
22impl Updater {
23 const SNARKOS_BIN_NAME: &'static str = "snarkos";
24 const SNARKOS_REPO_NAME: &'static str = "snarkOS";
25 const SNARKOS_REPO_OWNER: &'static str = "ProvableHQ";
26
27 pub fn show_available_releases() -> Result<String, UpdaterError> {
29 let releases = github::ReleaseList::configure()
30 .repo_owner(Self::SNARKOS_REPO_OWNER)
31 .repo_name(Self::SNARKOS_REPO_NAME)
32 .build()?
33 .fetch()?;
34
35 let mut output = "List of available versions\n".to_string();
36 for release in releases {
37 let _ = writeln!(output, " * {}", release.version);
38 }
39 Ok(output)
40 }
41
42 pub fn update_to_release(show_output: bool, version: Option<String>) -> Result<Status, UpdaterError> {
44 let mut update_builder = github::Update::configure();
45
46 update_builder
47 .repo_owner(Self::SNARKOS_REPO_OWNER)
48 .repo_name(Self::SNARKOS_REPO_NAME)
49 .bin_name(Self::SNARKOS_BIN_NAME)
50 .current_version(env!("CARGO_PKG_VERSION"))
51 .show_download_progress(show_output)
52 .no_confirm(true)
53 .show_output(show_output);
54
55 let status = match version {
56 None => update_builder.build()?.update()?,
57 Some(v) => update_builder.target_version_tag(&v).build()?.update()?,
58 };
59
60 Ok(status)
61 }
62
63 pub fn update_available() -> Result<String, UpdaterError> {
65 let updater = github::Update::configure()
66 .repo_owner(Self::SNARKOS_REPO_OWNER)
67 .repo_name(Self::SNARKOS_REPO_NAME)
68 .bin_name(Self::SNARKOS_BIN_NAME)
69 .current_version(env!("CARGO_PKG_VERSION"))
70 .build()?;
71
72 let current_version = updater.current_version();
73 let latest_release = updater.get_latest_release()?;
74
75 if bump_is_greater(¤t_version, &latest_release.version)? {
76 Ok(latest_release.version)
77 } else {
78 Err(UpdaterError::OldReleaseVersion(current_version, latest_release.version))
79 }
80 }
81
82 pub fn print_cli() -> Option<String> {
84 if let Ok(latest_version) = Self::update_available() {
85 let mut output = "🟢 A new version is available! Run".bold().green().to_string();
86 output += &" `snarkos update` ".bold().white();
87 output += &format!("to update to v{latest_version}.").bold().green();
88 Some(output)
89 } else {
90 None
91 }
92 }
93}
94
95#[derive(Debug, Error)]
96pub enum UpdaterError {
97 #[error("{}: {}", _0, _1)]
98 Crate(&'static str, String),
99
100 #[error("The current version {} is more recent than the release version {}", _0, _1)]
101 OldReleaseVersion(String, String),
102}
103
104impl From<self_update::errors::Error> for UpdaterError {
105 fn from(error: self_update::errors::Error) -> Self {
106 UpdaterError::Crate("self_update", error.to_string())
107 }
108}