From 1f5f5b8f9900d9a699c6cc14b0b1360b8c864549 Mon Sep 17 00:00:00 2001 From: Dmitry Konishchev Date: Wed, 31 Jul 2024 19:12:14 +0300 Subject: [PATCH] Introduce changelog configuration option --- src/config.rs | 2 ++ src/install.rs | 31 ++++++++++++++++++++++++++----- src/version.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/config.rs b/src/config.rs index 65b6dc9..509d9b3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -40,6 +40,8 @@ pub struct Tool { #[serde(default, deserialize_with = "deserialize_optional_glob")] pub binary_matcher: Option, + pub changelog: Option, + #[serde(default, deserialize_with = "deserialize_optional_path")] pub path: Option, } diff --git a/src/install.rs b/src/install.rs index 6f0bd71..18f670e 100644 --- a/src/install.rs +++ b/src/install.rs @@ -9,13 +9,14 @@ use easy_logging::GlobalContext; use globset::GlobMatcher; use itertools::Itertools; use log::{debug, info, error}; +use semver::Version; use url::Url; use crate::config::{Config, Tool}; use crate::core::{EmptyResult, GenericResult}; use crate::download; use crate::github; -use crate::version; +use crate::version::{self, ReleaseVersion}; #[derive(Clone, Copy, PartialEq)] pub enum Mode { @@ -67,7 +68,7 @@ fn install_tool(name: &str, tool: &Tool, mode: Mode, path: &Path) -> EmptyResult let release = github::get_release(&tool.project).map_err(|e| format!( "Failed to get latest release info for {project}: {e}"))?; - let release_version = &release.tag; + let release_version = ReleaseVersion::new(&release.tag); debug!("The latest release is {release_version}:"); for asset in &release.assets { @@ -103,7 +104,10 @@ fn install_tool(name: &str, tool: &Tool, mode: Mode, path: &Path) -> EmptyResult info!("Installing {name}..."); } else { match version::get_binary_version(&install_path) { - Some(current_version) => info!("Reinstalling {name}: {current_version} -> {release_version}..."), + Some(current_version) => info!( + "Reinstalling {name}: {current_version} -> {release_version}{changelog}...", + changelog=format_changelog(tool.changelog.as_deref(), Some(¤t_version), &release_version)), + None => info!("Reinstalling {name}..."), } }, @@ -117,8 +121,13 @@ fn install_tool(name: &str, tool: &Tool, mode: Mode, path: &Path) -> EmptyResult } match current_state.as_ref().and_then(|_| version::get_binary_version(&install_path)) { - Some(current_version) => info!("Upgrading {name}: {current_version} -> {release_version}..."), - None => info!("Upgrading {name} to {release_version}..."), + Some(current_version) => info!( + "Upgrading {name}: {current_version} -> {release_version}{changelog}...", + changelog=format_changelog(tool.changelog.as_deref(), Some(¤t_version), &release_version)), + + None => info!( + "Upgrading {name} to {release_version}{changelog}...", + changelog=format_changelog(tool.changelog.as_deref(), None, &release_version)), } }, } @@ -262,4 +271,16 @@ fn check_tool(path: &Path) -> GenericResult> { fn format_list>(mut iter: I) -> String { "\n* ".to_owned() + &iter.join("\n* ") +} + +fn format_changelog(changelog: Option<&str>, from: Option<&Version>, to: &ReleaseVersion) -> String { + let Some(changelog) = changelog else { + return String::new(); + }; + + if matches!((from, to), (Some(from), ReleaseVersion::Version(to)) if from == to) { + return String::new(); + } + + format!(" (see {changelog})") } \ No newline at end of file diff --git a/src/version.rs b/src/version.rs index 6c16355..de32521 100644 --- a/src/version.rs +++ b/src/version.rs @@ -1,9 +1,38 @@ +use std::fmt::{self, Display, Formatter}; use std::path::Path; use std::process::Command; use log::debug; use semver::Version; +pub enum ReleaseVersion { + Version(Version), + Tag(String) +} + +impl ReleaseVersion { + pub fn new(tag: &str) -> ReleaseVersion { + let mut version = tag; + if version.starts_with('v') { + version = &version[1..]; + } + + match Version::parse(version) { + Ok(version) => ReleaseVersion::Version(version), + Err(_) => ReleaseVersion::Tag(tag.to_owned()), + } + } +} + +impl Display for ReleaseVersion { + fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { + match self { + ReleaseVersion::Version(version) => version.fmt(formatter), + ReleaseVersion::Tag(tag) => tag.fmt(formatter), + } + } +} + pub fn get_binary_version(path: &Path) -> Option { let mut command = Command::new(path); command.arg("--version");