diff --git a/src/cmds/check.rs b/src/cmds/check.rs index 4d29d95..c855b15 100644 --- a/src/cmds/check.rs +++ b/src/cmds/check.rs @@ -29,7 +29,7 @@ fn print_update(update: &updates::Update, manifest: &manifest::Manifest) -> anyh } pub async fn run(args: &Args, config: &Config) -> anyhow::Result<()> { - let manifest = manifest::load_manifest(config, args.force).await?; + let manifest = manifest::load_latest_manifest(config, args.force).await?; let updates = updates::load_updates(&manifest, config, args.force).await?; diff --git a/src/cmds/install.rs b/src/cmds/install.rs index 2573ed1..44af735 100644 --- a/src/cmds/install.rs +++ b/src/cmds/install.rs @@ -21,8 +21,7 @@ use crate::{Config, manifest::*}; #[derive(Parser, Default)] pub struct Args { - pub tool: Option, - pub version: Option, + release: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -224,8 +223,11 @@ async fn install_tool(tool: &Tool, requested: &VersionReq, config: &Config) -> a Ok(()) } -pub async fn run(_args: &Args, config: &Config) -> anyhow::Result<()> { - let manifest = manifest::load_manifest(config, true).await?; +pub async fn run(args: &Args, config: &Config) -> anyhow::Result<()> { + let manifest = match &args.release { + Some(release) => manifest::load_tagged_manifest(config, release).await?, + None => manifest::load_latest_manifest(config, true).await?, + }; let updates = updates::check_updates(&manifest, config).await?; diff --git a/src/cmds/show.rs b/src/cmds/show.rs index 8ceaf71..26c4b46 100644 --- a/src/cmds/show.rs +++ b/src/cmds/show.rs @@ -35,7 +35,7 @@ fn print_tool(tool: &crate::manifest::Tool, config: &Config) -> anyhow::Result<( } pub async fn run(_args: &Args, config: &Config) -> anyhow::Result<()> { - let manifest = manifest::load_manifest(config, false).await?; + let manifest = manifest::load_latest_manifest(config, false).await?; for tool in manifest.tools() { println!("{}: {}", tool.name, tool.description); diff --git a/src/manifest.rs b/src/manifest.rs index 0ea79b9..ef49d74 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -1,5 +1,5 @@ use anyhow::Context; -use octocrab::Octocrab; +use octocrab::{Octocrab, models::repos::Release, repos::RepoHandler}; use reqwest::Client; use serde::{Deserialize, Serialize}; use std::{ @@ -54,18 +54,35 @@ async fn fetch_manifest_content(url: &str) -> anyhow::Result { Ok(data) } -pub async fn download_remote_manifest(config: &Config) -> anyhow::Result<()> { +async fn define_release( + repo: &RepoHandler<'_>, + explicit_tag: Option<&str>, +) -> anyhow::Result { + if let Some(explicit) = explicit_tag { + return repo + .releases() + .get_by_tag(explicit) + .await + .context("fetching release"); + } else { + repo.releases() + .get_latest() + .await + .context("fetching latest release") + } +} + +pub async fn download_remote_manifest( + config: &Config, + explicit_tag: Option<&str>, +) -> anyhow::Result<()> { let octocrab = Octocrab::builder() .build() - .map_err(|e| anyhow::anyhow!("Failed to create Octocrab client: {}", e))?; + .context("building octocrab client")?; let repo = octocrab.repos("tx3-lang", "toolchain"); - let release = repo - .releases() - .get_latest() - .await - .context("fetching latest release")?; + let release = define_release(&repo, explicit_tag).await?; let manifest_name = format!("manifest-{}.json", config.ensure_channel()); @@ -134,11 +151,14 @@ fn manifest_is_stale(timestamp: Option) -> bool { timestamp.is_none() || timestamp.unwrap() < SystemTime::now() - MANIFEST_STALE_THRESHOLD } -pub async fn load_manifest(config: &Config, force_download: bool) -> anyhow::Result { +pub async fn load_latest_manifest( + config: &Config, + force_download: bool, +) -> anyhow::Result { let timestamp = check_manifest_timestamp(config).await?; if manifest_is_stale(timestamp) || force_download { - download_remote_manifest(config).await?; + download_remote_manifest(config, None).await?; } let manifest = load_local_manifest(config) @@ -147,3 +167,13 @@ pub async fn load_manifest(config: &Config, force_download: bool) -> anyhow::Res Ok(manifest) } + +pub async fn load_tagged_manifest(config: &Config, explicit_tag: &str) -> anyhow::Result { + download_remote_manifest(config, Some(explicit_tag)).await?; + + let manifest = load_local_manifest(config) + .await? + .ok_or(anyhow::anyhow!("Manifest file should exist"))?; + + Ok(manifest) +}