diff --git a/CHANGELOG.md b/CHANGELOG.md index dc92aec..c19ddc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Fixed - Change dependency types for removed peer dependencies by @daimond113 +- Resolve version to correct tag for `pesde_version` field by @daimond113 ### Changed - Switch from `log` to `tracing` for logging by @daimond113 diff --git a/src/cli/commands/self_upgrade.rs b/src/cli/commands/self_upgrade.rs index 0426faf..1b3b19d 100644 --- a/src/cli/commands/self_upgrade.rs +++ b/src/cli/commands/self_upgrade.rs @@ -1,8 +1,8 @@ use crate::cli::{ config::read_config, version::{ - current_version, get_latest_remote_version, get_or_download_version, no_build_metadata, - update_bin_exe, + current_version, get_or_download_version, get_remote_version, no_build_metadata, + update_bin_exe, TagInfo, VersionType, }, }; use anyhow::Context; @@ -25,7 +25,7 @@ impl SelfUpgradeCommand { .context("no cached version found")? .1 } else { - get_latest_remote_version(&reqwest).await? + get_remote_version(&reqwest, VersionType::Latest).await? }; let latest_version_no_metadata = no_build_metadata(&latest_version); @@ -46,12 +46,12 @@ impl SelfUpgradeCommand { return Ok(()); } - let path = get_or_download_version(&reqwest, &latest_version, true) + let path = get_or_download_version(&reqwest, &TagInfo::Complete(latest_version), true) .await? .unwrap(); update_bin_exe(&path).await?; - println!("upgraded to version {display_latest_version}!",); + println!("upgraded to version {display_latest_version}!"); Ok(()) } diff --git a/src/cli/version.rs b/src/cli/version.rs index b4f7ae9..0c61bad 100644 --- a/src/cli/version.rs +++ b/src/cli/version.rs @@ -47,11 +47,20 @@ fn get_repo() -> (String, String) { (owner, repo) } +#[derive(Debug)] +pub enum VersionType { + Latest, + Specific(Version), +} + #[instrument(skip(reqwest), level = "trace")] -pub async fn get_latest_remote_version(reqwest: &reqwest::Client) -> anyhow::Result { +pub async fn get_remote_version( + reqwest: &reqwest::Client, + ty: VersionType, +) -> anyhow::Result { let (owner, repo) = get_repo(); - let releases = reqwest + let mut releases = reqwest .get(format!( "https://api.github.com/repos/{owner}/{repo}/releases", )) @@ -62,13 +71,17 @@ pub async fn get_latest_remote_version(reqwest: &reqwest::Client) -> anyhow::Res .context("failed to get GitHub API response")? .json::>() .await - .context("failed to parse GitHub API response")?; - - releases + .context("failed to parse GitHub API response")? .into_iter() - .filter_map(|release| Version::parse(release.tag_name.trim_start_matches('v')).ok()) - .max() - .context("failed to find latest version") + .filter_map(|release| Version::parse(release.tag_name.trim_start_matches('v')).ok()); + + match ty { + VersionType::Latest => releases.max(), + VersionType::Specific(version) => { + releases.find(|v| no_build_metadata(v) == no_build_metadata(&version)) + } + } + .context("failed to find latest version") } pub fn no_build_metadata(version: &Version) -> Version { @@ -91,7 +104,7 @@ pub async fn check_for_updates(reqwest: &reqwest::Client) -> anyhow::Result<()> version } else { tracing::debug!("checking for updates"); - let version = get_latest_remote_version(reqwest).await?; + let version = get_remote_version(reqwest, VersionType::Latest).await?; write_config(&CliConfig { last_checked_updates: Some((chrono::Utc::now(), version.clone())), @@ -229,10 +242,16 @@ pub async fn download_github_release( .map(|_| ()) } +#[derive(Debug)] +pub enum TagInfo { + Complete(Version), + Incomplete(Version), +} + #[instrument(skip(reqwest), level = "trace")] pub async fn get_or_download_version( reqwest: &reqwest::Client, - version: &Version, + tag: &TagInfo, always_give_path: bool, ) -> anyhow::Result> { let path = home_dir()?.join("versions"); @@ -240,7 +259,17 @@ pub async fn get_or_download_version( .await .context("failed to create versions directory")?; - let path = path.join(format!("{version}{}", std::env::consts::EXE_SUFFIX)); + let version = match tag { + TagInfo::Complete(version) => version, + // don't fetch the version since it could be cached + TagInfo::Incomplete(version) => version, + }; + + let path = path.join(format!( + "{}{}", + no_build_metadata(version), + std::env::consts::EXE_SUFFIX + )); let is_requested_version = !always_give_path && *version == current_version(); @@ -260,10 +289,19 @@ pub async fn get_or_download_version( .await .context("failed to copy current executable to version directory")?; } else { + let version = match tag { + TagInfo::Complete(version) => version.clone(), + TagInfo::Incomplete(version) => { + get_remote_version(reqwest, VersionType::Specific(version.clone())) + .await + .context("failed to get remote version")? + } + }; + tracing::debug!("downloading version"); download_github_release( reqwest, - version, + &version, fs::File::create(&path) .await .context("failed to create version file")?, diff --git a/src/main.rs b/src/main.rs index abaf113..9d16712 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ #[cfg(feature = "version-management")] -use crate::cli::version::{check_for_updates, get_or_download_version}; +use crate::cli::version::{check_for_updates, get_or_download_version, TagInfo}; use crate::cli::{auth::get_tokens, display_err, home_dir, HOME_DIR}; use anyhow::Context; use clap::{builder::styling::AnsiColor, Parser}; @@ -281,7 +281,7 @@ async fn run() -> anyhow::Result<()> { .and_then(|manifest| manifest.pesde_version); let exe_path = if let Some(version) = target_version { - get_or_download_version(&reqwest, &version, false).await? + get_or_download_version(&reqwest, &TagInfo::Incomplete(version), false).await? } else { None };