mirror of
https://github.com/louis-e/arnis.git
synced 2026-04-22 15:10:10 -04:00
Prevent startup hangs from stalled connections by adding a 5s connect timeout and 10s total timeout to the update check.
86 lines
3.2 KiB
Rust
86 lines
3.2 KiB
Rust
use colored::Colorize;
|
|
use reqwest::blocking::Client;
|
|
use reqwest::{Error as ReqwestError, StatusCode};
|
|
use semver::Version;
|
|
use std::error::Error;
|
|
use std::time::Duration;
|
|
|
|
/// URL to the remote Cargo.toml file to check for the latest version
|
|
const REMOTE_CARGO_TOML_URL: &str =
|
|
"https://raw.githubusercontent.com/louis-e/arnis/main/Cargo.toml";
|
|
|
|
/// Fetches the latest version from the remote Cargo.toml file and compares it with the local version.
|
|
/// Returns `true` if a newer version is available, `false` otherwise.
|
|
pub fn check_for_updates() -> Result<bool, Box<dyn Error>> {
|
|
let client: Client = Client::builder()
|
|
.user_agent(concat!("arnis/", env!("CARGO_PKG_VERSION")))
|
|
.connect_timeout(Duration::from_secs(5))
|
|
.timeout(Duration::from_secs(10))
|
|
.build()?;
|
|
|
|
// Fetch the remote Cargo.toml file
|
|
let response: Result<reqwest::blocking::Response, ReqwestError> =
|
|
client.get(REMOTE_CARGO_TOML_URL).send();
|
|
|
|
match response {
|
|
Ok(res) => {
|
|
// If the response status is not 200 OK, handle it as an HTTP error
|
|
if !res.status().is_success() {
|
|
handle_http_error(res.status());
|
|
return Ok(false);
|
|
}
|
|
|
|
let response_text: String = res.text()?;
|
|
// Extract the version from the remote Cargo.toml
|
|
let remote_version: Version = extract_version_from_cargo_toml(&response_text)?;
|
|
let local_version: Version = Version::parse(env!("CARGO_PKG_VERSION"))?;
|
|
|
|
// Compare versions
|
|
if remote_version > local_version {
|
|
println!(
|
|
"{} {} -> {}",
|
|
"A new version is available:".yellow().bold(),
|
|
local_version,
|
|
remote_version
|
|
);
|
|
return Ok(true); // Newer version is available
|
|
}
|
|
|
|
Ok(false) // Local version is up-to-date
|
|
}
|
|
Err(err) => {
|
|
handle_request_error(err);
|
|
Ok(false) // Treat request failures as no new version available
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Extracts the version from the contents of a Cargo.toml file.
|
|
fn extract_version_from_cargo_toml(cargo_toml_contents: &str) -> Result<Version, Box<dyn Error>> {
|
|
for line in cargo_toml_contents.lines() {
|
|
if line.starts_with("version") {
|
|
let version_str: &str = line.split('=').nth(1).unwrap().trim().trim_matches('"');
|
|
return Ok(Version::parse(version_str)?);
|
|
}
|
|
}
|
|
Err("Failed to find version in Cargo.toml".into())
|
|
}
|
|
|
|
/// Handles HTTP errors by printing the status code and a user-friendly message.
|
|
fn handle_http_error(status: StatusCode) {
|
|
eprintln!(
|
|
"Failed to fetch remote Cargo.toml: HTTP error {}: {}",
|
|
status.as_u16(),
|
|
status.canonical_reason().unwrap_or("Unknown error")
|
|
);
|
|
}
|
|
|
|
/// Handles the error for HTTP requests more gracefully, including printing HTTP status codes when applicable.
|
|
fn handle_request_error(err: ReqwestError) {
|
|
if err.is_timeout() {
|
|
eprintln!("Request timed out. Please check your network connection.");
|
|
} else if let Some(status) = err.status() {
|
|
handle_http_error(status);
|
|
}
|
|
}
|