diff --git a/Cargo.lock b/Cargo.lock index f4c0e86..565a237 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -958,13 +958,14 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustfinity" -version = "0.2.7" +version = "0.2.8" dependencies = [ "anyhow", "clap", "dload", "futures", "reqwest", + "serde_json", "tokio", ] @@ -1063,9 +1064,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 49edd5f..4d21fd2 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfinity" -version = "0.2.7" +version = "0.2.8" edition = "2021" license = "MIT" description = "Rustfinity.com CLI" @@ -11,5 +11,6 @@ anyhow = "1.0.82" clap = { version = "4.5.4", features = ["derive"] } dload = "0.1.3" futures = "0.3.30" -reqwest = "0.12.4" +reqwest = { version = "0.12.4", features = ["json"] } +serde_json = "1.0.117" tokio = { version = "1.37.0", features = ["full"] } diff --git a/crates/cli/src/crates_io.rs b/crates/cli/src/crates_io.rs new file mode 100644 index 0000000..6369b7c --- /dev/null +++ b/crates/cli/src/crates_io.rs @@ -0,0 +1,34 @@ +pub async fn get_latest_version() -> anyhow::Result { + let url = "https://crates.io/api/v1/crates/rustfinity"; + + let client = reqwest::ClientBuilder::new() + .user_agent("rustfinity") + .build()?; + + let response = client.get(url).send().await?; + let json: serde_json::Value = response.json().await?; + + let latest_version = json["crate"]["newest_version"] + .as_str() + .ok_or(anyhow::anyhow!("Failed to get latest version"))?; + + Ok(latest_version.to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_get_latest_version() { + let version = get_latest_version().await.unwrap(); + assert!(!version.is_empty()); + + // Expect the pattern to be "x.x.x" while x is a number + let mut version = version.split('.'); + assert!(version.next().unwrap().parse::().is_ok()); + assert!(version.next().unwrap().parse::().is_ok()); + assert!(version.next().unwrap().parse::().is_ok()); + assert!(version.next().is_none()); + } +} diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 03ebc1b..5c80dab 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,5 +1,6 @@ mod challenge; mod cli; +mod crates_io; mod download; use clap::Parser; @@ -7,6 +8,17 @@ use cli::{run, Cli}; #[tokio::main] async fn main() -> anyhow::Result<()> { + let latest_version = crates_io::get_latest_version().await?; + let current_version = env!("CARGO_PKG_VERSION"); + + if latest_version != current_version { + println!( + "A new version of rustfinity ({}) is available, please run the following command and try again:\n\n$ cargo install rustfinity", + latest_version + ); + return Ok(()); + } + let cli = Cli::parse(); run(cli).await }