Skip to content

Commit

Permalink
wip, review
Browse files Browse the repository at this point in the history
  • Loading branch information
overcat committed Aug 29, 2024
1 parent 8a3e56b commit cb72bec
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 37 deletions.
4 changes: 2 additions & 2 deletions cmd/soroban-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use dotenvy::dotenv;
use std::thread;
use tracing_subscriber::{fmt, EnvFilter};

use crate::self_outdated_check::print_upgrade_prompt;
use crate::upgrade_check::upgrade_check;
use crate::{commands, Root};

#[tokio::main]
pub async fn main() {
// Spawn a thread to print the upgrade prompt in the background
thread::spawn(print_upgrade_prompt);
thread::spawn(upgrade_check);

let _ = dotenv().unwrap_or_default();

Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub mod data;
pub mod locator;
pub mod network;
pub mod secret;
pub mod self_outdated_check;
pub mod upgrade_check;

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ use crate::config::locator;
use jsonrpsee_core::Serialize;
use semver::Version;
use serde::Deserialize;
use serde_json;
use std::fs;

const FILE_NAME: &str = "self_outdated_check.toml";
const FILE_NAME: &str = "upgrade_check.json";

/// The `SelfOutdatedCheck` struct represents the state of the self-outdated check.
/// This state is global and stored in the `self_outdated_check.toml` file in
/// This state is global and stored in the `self_outdated_check.json` file in
/// the global configuration directory.
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct SelfOutdatedCheck {
pub struct UpgradeCheck {
/// The timestamp of the latest check for a new version of the CLI.
pub latest_check_time: u64,
/// The latest stable version of the CLI available on crates.io.
Expand All @@ -19,7 +20,7 @@ pub struct SelfOutdatedCheck {
pub max_version: Version,
}

impl Default for SelfOutdatedCheck {
impl Default for UpgradeCheck {
fn default() -> Self {
Self {
latest_check_time: 0,
Expand All @@ -29,7 +30,7 @@ impl Default for SelfOutdatedCheck {
}
}

impl SelfOutdatedCheck {
impl UpgradeCheck {
/// Loads the state of the self-outdated check from the global configuration directory.
/// If the file doesn't exist, returns a default instance of `SelfOutdatedCheck`.
pub fn load() -> Result<Self, locator::Error> {
Expand All @@ -39,14 +40,14 @@ impl SelfOutdatedCheck {
}
let data = fs::read(&path)
.map_err(|error| locator::Error::SelfOutdatedCheckReadFailed { path, error })?;
Ok(toml::from_slice(data.as_slice())?)
Ok(serde_json::from_slice(data.as_slice())?)
}

/// Saves the state of the self-outdated check to the `self_outdated_check.toml` file in the global configuration directory.
/// Saves the state of the self-outdated check to the `self_outdated_check.json` file in the global configuration directory.
pub fn save(&self) -> Result<(), locator::Error> {
let path = locator::global_config_path()?.join(FILE_NAME);
let path = locator::ensure_directory(path)?;
let data = toml::to_string(self).map_err(|_| locator::Error::ConfigSerialization)?;
let data = serde_json::to_string(self).map_err(|_| locator::Error::ConfigSerialization)?;
fs::write(&path, data)
.map_err(|error| locator::Error::SelfOutdatedCheckWriteFailed { path, error })
}
Expand All @@ -64,19 +65,19 @@ mod tests {
env::set_var("XDG_CONFIG_HOME", temp_dir.path());

// Test default loading
let default_check = SelfOutdatedCheck::load().unwrap();
assert_eq!(default_check, SelfOutdatedCheck::default());
let default_check = UpgradeCheck::load().unwrap();
assert_eq!(default_check, UpgradeCheck::default());
assert_eq!(default_check.latest_check_time, 0);
assert_eq!(default_check.max_stable_version, Version::new(0, 0, 0));

// Test saving and loading
let saved_check = SelfOutdatedCheck {
let saved_check = UpgradeCheck {
latest_check_time: 1_234_567_890,
max_stable_version: Version::new(1, 2, 3),
max_version: Version::parse("1.2.4-rc.1").unwrap(),
};
saved_check.save().unwrap();
let loaded_check = SelfOutdatedCheck::load().unwrap();
let loaded_check = UpgradeCheck::load().unwrap();
assert_eq!(loaded_check, saved_check);
}
}
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ pub mod get_spec;
pub mod key;
pub mod log;
pub mod print;
pub mod self_outdated_check;
pub mod signer;
pub mod toid;
pub mod upgrade_check;
pub mod utils;
pub mod wasm;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::config::self_outdated_check::SelfOutdatedCheck;
use crate::print::Print;
use crate::config::upgrade_check::UpgradeCheck;
use semver::Version;
use serde::Deserialize;
use std::error::Error;
Expand Down Expand Up @@ -35,7 +34,7 @@ fn fetch_latest_crate_info() -> Result<Crate, Box<dyn Error>> {
}

/// Print a warning if a new version of the CLI is available
pub fn print_upgrade_prompt() {
pub fn upgrade_check() {
// We should skip the upgrade check if we're not in a tty environment.
if !std::io::stderr().is_terminal() {
return;
Expand All @@ -48,15 +47,11 @@ pub fn print_upgrade_prompt() {
}

let current_version = crate::commands::version::pkg();
let print = Print::new(false);

let mut stats = match SelfOutdatedCheck::load() {
Ok(stats) => stats,
Err(e) => {
print.warnln(format!("Failed to load self outdated check data: {}", e));
SelfOutdatedCheck::default()
}
};
let mut stats = UpgradeCheck::load().unwrap_or_else(|e| {
println!("Failed to load self outdated check data: {e}");
UpgradeCheck::default()
});

#[allow(clippy::cast_sign_loss)]
let now = chrono::Utc::now().timestamp() as u64;
Expand All @@ -65,39 +60,36 @@ pub fn print_upgrade_prompt() {
if now - stats.latest_check_time >= MINIMUM_CHECK_INTERVAL.as_secs() {
match fetch_latest_crate_info() {
Ok(c) => {
stats = SelfOutdatedCheck {
stats = UpgradeCheck {
latest_check_time: now,
max_stable_version: c.max_stable_version,
max_version: c.max_version,
};
}
Err(e) => {
print.warnln(format!(
"Failed to fetch stellar-cli info from crates.io: {}",
e
));
println!("Failed to fetch stellar-cli info from crates.io: {e}");
// Only update the latest check time if the fetch failed
// This way we don't spam the user with errors
stats.latest_check_time = now;
}
}

if let Err(e) = stats.save() {
print.warnln(format!("Failed to save self outdated check data: {}", e));
println!("Failed to save self outdated check data: {e}");
}
}

let current_version = Version::parse(current_version).unwrap();
let latest_version = get_latest_version(&current_version, &stats);

if *latest_version > current_version {
print.warnln(format!(
println!(
"A new release of stellar-cli is available: {current_version} -> {latest_version}",
));
);
}
}

fn get_latest_version<'a>(current_version: &Version, stats: &'a SelfOutdatedCheck) -> &'a Version {
fn get_latest_version<'a>(current_version: &Version, stats: &'a UpgradeCheck) -> &'a Version {
if current_version.pre.is_empty() {
// If we are currently using a non-preview version
&stats.max_stable_version
Expand All @@ -123,7 +115,7 @@ mod tests {

#[test]
fn test_get_latest_version() {
let stats = SelfOutdatedCheck {
let stats = UpgradeCheck {
latest_check_time: 0,
max_stable_version: Version::parse("1.0.0").unwrap(),
max_version: Version::parse("1.1.0-rc.1").unwrap(),
Expand Down

0 comments on commit cb72bec

Please sign in to comment.