Notify the user if there is a new version of lprs
This commit is contained in:
parent
44fa47d953
commit
4f263aa28e
2 changed files with 85 additions and 19 deletions
26
src/main.rs
26
src/main.rs
|
@ -30,15 +30,37 @@ pub mod utils;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod traits;
|
mod traits;
|
||||||
|
|
||||||
|
pub use errors::{Error as LprsError, Result as LprsResult};
|
||||||
pub use traits::*;
|
pub use traits::*;
|
||||||
|
|
||||||
pub use errors::{Error as LprsError, Result as LprsResult};
|
|
||||||
|
|
||||||
pub const STANDARDBASE: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, PAD);
|
pub const STANDARDBASE: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, PAD);
|
||||||
|
pub const DEFAULT_PASSWORD_FILE: &str = "passwords.json";
|
||||||
|
|
||||||
|
#[cfg(feature = "update-notify")]
|
||||||
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
#[cfg(feature = "update-notify")]
|
||||||
|
pub const LAST_VERSION_CHECK_FILE: &str = ".last_version_check";
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
|
#[cfg(feature = "update-notify")]
|
||||||
|
{
|
||||||
|
match utils::lprs_version() {
|
||||||
|
Ok(Some(new_version)) => {
|
||||||
|
println!(
|
||||||
|
"Warning: The version you are using of lprs is outdated. There is a newer version, which is `{new_version}`, and your version is `{VERSION}`
|
||||||
|
\rYou can update via: `cargo install lprs -F update-notify --locked`\n\n"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{err}");
|
||||||
|
return ExitCode::FAILURE;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(err) = cli::Cli::parse().run() {
|
if let Err(err) = cli::Cli::parse().run() {
|
||||||
eprintln!("{err}");
|
eprintln!("{err}");
|
||||||
err.exit_code()
|
err.exit_code()
|
||||||
|
|
78
src/utils.rs
78
src/utils.rs
|
@ -18,21 +18,65 @@ use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
use crate::{LprsError, LprsResult};
|
use crate::{LprsError, LprsResult};
|
||||||
|
|
||||||
/// Return the default passwords json file
|
/// Returns the local project dir joined with the given file name
|
||||||
pub fn passwords_file() -> LprsResult<PathBuf> {
|
pub fn local_project_file(filename: &str) -> LprsResult<PathBuf> {
|
||||||
if let Some(path) = directories::ProjectDirs::from("", "", "lprs")
|
directories::ProjectDirs::from("", "", "lprs")
|
||||||
.map(|d| d.data_local_dir().to_path_buf().join("passwords.json"))
|
.map(|d| d.data_local_dir().to_path_buf().join(filename))
|
||||||
{
|
.ok_or_else(|| {
|
||||||
if let Some(parent) = path.parent() {
|
LprsError::ProjectDir("Can't extract the project_dir from this OS".to_owned())
|
||||||
std::fs::create_dir_all(parent)?;
|
})
|
||||||
}
|
}
|
||||||
if !path.exists() {
|
|
||||||
fs::write(&path, "[]")?;
|
/// Returns the default passwords json file
|
||||||
}
|
pub fn passwords_file() -> LprsResult<PathBuf> {
|
||||||
Ok(path)
|
let password_file = local_project_file(crate::DEFAULT_PASSWORD_FILE)?;
|
||||||
} else {
|
if let Some(parent) = password_file.parent() {
|
||||||
Err(LprsError::ProjectDir(
|
std::fs::create_dir_all(parent)?;
|
||||||
"Can't extract the project_dir from this OS".to_owned(),
|
}
|
||||||
))
|
if !password_file.exists() {
|
||||||
}
|
fs::write(&password_file, "[]")?;
|
||||||
|
}
|
||||||
|
Ok(password_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retuns the current lprs version from `crates.io`
|
||||||
|
#[cfg(feature = "update-notify")]
|
||||||
|
pub fn lprs_version() -> LprsResult<Option<String>> {
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
let last_version_check_file = local_project_file(crate::LAST_VERSION_CHECK_FILE)?;
|
||||||
|
let current_time = SystemTime::now()
|
||||||
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
|
.map_err(|_| LprsError::Other("The system time is before UNIX EPOCH!".to_owned()))?
|
||||||
|
.as_secs();
|
||||||
|
let last_check: u64 = fs::read_to_string(&last_version_check_file)
|
||||||
|
.unwrap_or_else(|_| current_time.to_string())
|
||||||
|
.parse()
|
||||||
|
.map_err(|err| {
|
||||||
|
LprsError::Other(format!(
|
||||||
|
"Check update file content is invalid time `{}`: {err}",
|
||||||
|
last_version_check_file.display()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
fs::write(last_version_check_file, current_time.to_string())?;
|
||||||
|
|
||||||
|
// Check if the last check is before one hour or not
|
||||||
|
if (current_time - last_check) >= (60 * 60) || current_time == last_check {
|
||||||
|
if let Ok(Ok(response)) = reqwest::blocking::Client::new()
|
||||||
|
.get("https://crates.io/api/v1/crates/lprs")
|
||||||
|
.header(
|
||||||
|
"User-Agent",
|
||||||
|
format!("Lprs <{current_time}> (https://github.com/theawiteb/lprs)"),
|
||||||
|
)
|
||||||
|
.send()
|
||||||
|
.map(|r| r.text())
|
||||||
|
{
|
||||||
|
let re =
|
||||||
|
regex::Regex::new(r#""max_stable_version":"(?<version>\d+\.\d+\.\d+)""#).unwrap();
|
||||||
|
if let Some(cap) = re.captures(&response) {
|
||||||
|
return Ok(cap.name("version").map(|m| m.as_str().to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue