From 1b068be2d2d2ed7f164739cc1d1f7f6f37c0a126 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:41:31 -0600 Subject: [PATCH] fix: upgrade with options Fixes #2890 --- .mise.toml | 1 + e2e/cli/test_upgrade | 10 ++++++ src/cli/args/backend_arg.rs | 1 + src/cli/upgrade.rs | 2 +- src/cli/use.rs | 6 ++-- src/config/config_file/legacy_version.rs | 8 +++-- src/config/config_file/mise_toml.rs | 43 +++++++++++++++++++----- src/config/config_file/mod.rs | 12 ++++--- src/config/config_file/tool_versions.rs | 9 +++-- 9 files changed, 71 insertions(+), 21 deletions(-) diff --git a/.mise.toml b/.mise.toml index d618a13df9..4d574face7 100644 --- a/.mise.toml +++ b/.mise.toml @@ -26,6 +26,7 @@ actionlint = "latest" ripgrep = "latest" "pipx:toml-sort" = "latest" "cargo:usage-cli" = "1" +"ubi:bazelbuild/buildtools" = "7.3.1" #python = { version = "latest", virtualenv = "{{env.HOME}}/.cache/venv" } #ruby = "3.1" diff --git a/e2e/cli/test_upgrade b/e2e/cli/test_upgrade index b763cbd47f..93410761dc 100644 --- a/e2e/cli/test_upgrade +++ b/e2e/cli/test_upgrade @@ -14,3 +14,13 @@ assert_not_contains "mise ls --installed dummy" "1.0.0" mise upgrade dummy --bump assert_contains "mise ls --installed dummy" "2.0.0" assert_not_contains "mise ls --installed dummy" "1.1.0" +rm .tool-versions + +# ensure options are retained +mise use "ubi:bazelbuild/buildtools[exe=buildifier,matching=buildifier]@7.1.2" +assert "cat .mise.toml" '[tools] +"ubi:bazelbuild/buildtools" = { version = "7.1.2", exe = "buildifier", matching = "buildifier" }' +bazelbuild_latest=$(mise latest ubi:bazelbuild/buildtools) +mise up --bump ubi:bazelbuild/buildtools +assert "cat .mise.toml" "[tools] +\"ubi:bazelbuild/buildtools\" = { version = \"$bazelbuild_latest\", exe = \"buildifier\", matching = \"buildifier\" }" diff --git a/src/cli/args/backend_arg.rs b/src/cli/args/backend_arg.rs index e780df40dc..13e5423837 100644 --- a/src/cli/args/backend_arg.rs +++ b/src/cli/args/backend_arg.rs @@ -49,6 +49,7 @@ impl From for BackendArg { impl BackendArg { pub fn new(short: &str, full: &str) -> Self { let short = unalias_backend(short).to_string(); + let short = regex!(r#"\[.+\]$"#).replace_all(&short, "").to_string(); let (backend, mut name) = full.split_once(':').unwrap_or(("", full)); diff --git a/src/cli/upgrade.rs b/src/cli/upgrade.rs index 810124cbb2..b7606d0807 100644 --- a/src/cli/upgrade.rs +++ b/src/cli/upgrade.rs @@ -150,7 +150,7 @@ impl Upgrade { let versions = ts.install_versions(config, new_versions, &mpr, &opts)?; for (o, bump, mut cf) in config_file_updates { - cf.replace_versions(o.tool_request.backend(), &[bump])?; + cf.replace_versions(o.tool_request.backend(), &[(bump, o.tool_request.options())])?; cf.save()?; } diff --git a/src/cli/use.rs b/src/cli/use.rs index e6e8d0c176..8709d767b4 100644 --- a/src/cli/use.rs +++ b/src/cli/use.rs @@ -113,13 +113,13 @@ impl Use { let pin = self.pin || !self.fuzzy && (SETTINGS.pin || SETTINGS.asdf_compat); for (fa, tvl) in &versions.iter().chunk_by(|tv| &tv.backend) { - let versions: Vec = tvl + let versions: Vec<_> = tvl .into_iter() .map(|tv| { if pin { - tv.version.clone() + (tv.version.clone(), tv.request.options()) } else { - tv.request.version() + (tv.request.version(), tv.request.options()) } }) .collect(); diff --git a/src/config/config_file/legacy_version.rs b/src/config/config_file/legacy_version.rs index 30f0a76531..0465e7d1ad 100644 --- a/src/config/config_file/legacy_version.rs +++ b/src/config/config_file/legacy_version.rs @@ -5,7 +5,7 @@ use eyre::Result; use crate::backend::{self, BackendList}; use crate::cli::args::BackendArg; use crate::config::config_file::ConfigFile; -use crate::toolset::{ToolRequest, ToolRequestSet, ToolSource}; +use crate::toolset::{ToolRequest, ToolRequestSet, ToolSource, ToolVersionOptions}; #[derive(Debug, Clone)] pub struct LegacyVersionFile { @@ -59,7 +59,11 @@ impl ConfigFile for LegacyVersionFile { unimplemented!() } - fn replace_versions(&mut self, _plugin_name: &BackendArg, _versions: &[String]) -> Result<()> { + fn replace_versions( + &mut self, + _plugin_name: &BackendArg, + _versions: &[(String, ToolVersionOptions)], + ) -> Result<()> { unimplemented!() } diff --git a/src/config/config_file/mise_toml.rs b/src/config/config_file/mise_toml.rs index 6cf2ff39e5..1c7efc9da5 100644 --- a/src/config/config_file/mise_toml.rs +++ b/src/config/config_file/mise_toml.rs @@ -10,7 +10,7 @@ use serde::de::Visitor; use serde::{de, Deserializer}; use serde_derive::Deserialize; use tera::Context as TeraContext; -use toml_edit::{table, value, Array, DocumentMut, Item, Value}; +use toml_edit::{table, value, Array, DocumentMut, InlineTable, Item, Value}; use versions::Versioning; use crate::cli::args::{BackendArg, ToolVersionType}; @@ -279,12 +279,21 @@ impl ConfigFile for MiseToml { Ok(()) } - fn replace_versions(&mut self, fa: &BackendArg, versions: &[String]) -> eyre::Result<()> { - self.tools.entry(fa.clone()).or_default().0 = versions + fn replace_versions( + &mut self, + fa: &BackendArg, + versions: &[(String, ToolVersionOptions)], + ) -> eyre::Result<()> { + let existing = self.tools.entry(fa.clone()).or_default(); + existing.0 = versions .iter() - .map(|v| MiseTomlTool { + .map(|(v, opts)| MiseTomlTool { tt: ToolVersionType::Version(v.clone()), - options: Default::default(), + options: if !opts.is_empty() { + Some(opts.clone()) + } else { + None + }, }) .collect(); let tools = self @@ -298,11 +307,29 @@ impl ConfigFile for MiseToml { tools.remove(&fa.full.to_string()); if versions.len() == 1 { - tools.insert(&fa.short, value(versions[0].clone())); + if versions[0].1.is_empty() { + tools.insert(&fa.short, value(versions[0].0.clone())); + } else { + let mut table = InlineTable::new(); + table.insert("version", versions[0].0.to_string().into()); + for (k, v) in &versions[0].1 { + table.insert(k, v.clone().into()); + } + tools.insert(&fa.short, table.into()); + } } else { let mut arr = Array::new(); - for v in versions { - arr.push(v); + for (v, opts) in versions { + if opts.is_empty() { + arr.push(v.to_string()); + } else { + let mut table = InlineTable::new(); + table.insert("version", v.to_string().into()); + for (k, v) in opts { + table.insert(k, v.clone().into()); + } + arr.push(table); + } } tools.insert(&fa.short, Item::Value(Value::Array(arr))); } diff --git a/src/config/config_file/mod.rs b/src/config/config_file/mod.rs index 2d3231d5a4..ad64c41c1c 100644 --- a/src/config/config_file/mod.rs +++ b/src/config/config_file/mod.rs @@ -21,7 +21,7 @@ use crate::errors::Error::UntrustedConfig; use crate::file::display_path; use crate::hash::{file_hash_sha256, hash_to_str}; use crate::task::Task; -use crate::toolset::{ToolRequestSet, ToolSource, ToolVersionList, Toolset}; +use crate::toolset::{ToolRequestSet, ToolSource, ToolVersionList, ToolVersionOptions, Toolset}; use crate::ui::{prompt, style}; use crate::{backend, dirs, env, file}; @@ -71,7 +71,11 @@ pub trait ConfigFile: Debug + Send + Sync { Default::default() } fn remove_plugin(&mut self, _fa: &BackendArg) -> eyre::Result<()>; - fn replace_versions(&mut self, fa: &BackendArg, versions: &[String]) -> eyre::Result<()>; + fn replace_versions( + &mut self, + fa: &BackendArg, + versions: &[(String, ToolVersionOptions)], + ) -> eyre::Result<()>; fn save(&self) -> eyre::Result<()>; fn dump(&self) -> eyre::Result; fn source(&self) -> ToolSource; @@ -121,9 +125,9 @@ impl dyn ConfigFile { if pin { let plugin = backend::get(&fa); let tv = tvr.resolve(plugin.as_ref(), &Default::default())?; - Ok(tv.version) + Ok((tv.version, tv.request.options())) } else { - Ok(tvr.version()) + Ok((tvr.version(), tvr.options())) } }) .collect::>>()?; diff --git a/src/config/config_file/tool_versions.rs b/src/config/config_file/tool_versions.rs index d456230fe8..f458a0312a 100644 --- a/src/config/config_file/tool_versions.rs +++ b/src/config/config_file/tool_versions.rs @@ -13,7 +13,7 @@ use crate::config::config_file::ConfigFile; use crate::file; use crate::file::display_path; use crate::tera::{get_tera, BASE_CONTEXT}; -use crate::toolset::{ToolRequest, ToolRequestSet, ToolSource}; +use crate::toolset::{ToolRequest, ToolRequestSet, ToolSource, ToolVersionOptions}; // python 3.11.0 3.10.0 // shellcheck 0.9.0 @@ -162,9 +162,12 @@ impl ConfigFile for ToolVersions { Ok(()) } - fn replace_versions(&mut self, fa: &BackendArg, versions: &[String]) -> eyre::Result<()> { + fn replace_versions(&mut self, fa: &BackendArg, versions: &[(String, ToolVersionOptions)]) -> eyre::Result<()> { self.get_or_create_plugin(fa).versions.clear(); - for version in versions { + for (version, opts) in versions { + if !opts.is_empty() { + warn!("tool options are not supported in .tool-versions files"); + } self.add_version(fa, version); } Ok(())