From 1fe90ef7f42548511e22b5d604bb906eeec6f1ab Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 15 Nov 2022 16:14:10 -0500 Subject: [PATCH] Only notify once for each app update (#762) --- src/main.rs | 2 +- src/updates.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 556a8f649c..8c3fda6bb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -379,7 +379,7 @@ fn inner_main() -> Result { // Check for updates if we're in a non-silent log level. #[cfg(feature = "update-informer")] if !is_stdin && log_level >= LogLevel::Default && atty::is(atty::Stream::Stdout) { - updates::check_for_updates(); + let _ = updates::check_for_updates(); } if messages.iter().any(|message| !message.fixed) && !cli.exit_zero { diff --git a/src/updates.rs b/src/updates.rs index 1ba303a7cd..45ab319a5b 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -1,19 +1,65 @@ +use std::fs::{create_dir_all, read_to_string, File}; +use std::io::Write; +use std::path::{Path, PathBuf}; + +use anyhow::Result; use colored::Colorize; const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME"); const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub fn check_for_updates() { +fn cache_dir() -> &'static str { + "./.ruff_cache" +} + +fn file_path() -> PathBuf { + Path::new(cache_dir()).join(".update-informer") +} + +/// Get the "latest" version for which the user has been informed. +fn get_latest() -> Result> { + let path = file_path(); + if path.exists() { + Ok(Some(read_to_string(path)?.trim().to_string())) + } else { + Ok(None) + } +} + +/// Set the "latest" version for which the user has been informed. +fn set_latest(version: &str) -> Result<()> { + create_dir_all(cache_dir())?; + let path = file_path(); + let mut file = File::create(path)?; + file.write_all(version.trim().as_bytes()) + .map_err(|e| e.into()) +} + +/// Update the user if a newer version is available. +pub fn check_for_updates() -> Result<()> { use update_informer::{registry, Check}; let informer = update_informer::new(registry::PyPI, CARGO_PKG_NAME, CARGO_PKG_VERSION); - if let Some(new_version) = informer.check_version().ok().flatten() { + if let Some(new_version) = informer + .check_version() + .ok() + .flatten() + .map(|version| version.to_string()) + { + // If we've already notified the user about this version, return early. + if let Some(latest_version) = get_latest()? { + if latest_version == new_version { + return Ok(()); + } + } + set_latest(&new_version)?; + let msg = format!( "A new version of {pkg_name} is available: v{pkg_version} -> {new_version}", pkg_name = CARGO_PKG_NAME.italic().cyan(), pkg_version = CARGO_PKG_VERSION, - new_version = new_version.to_string().green() + new_version = new_version.green() ); let cmd = format!( @@ -24,4 +70,6 @@ pub fn check_for_updates() { println!("\n{msg}\n{cmd}"); } + + Ok(()) }