diff --git a/.mise.toml b/.mise.toml index 100e1ac43a..ff81514d63 100644 --- a/.mise.toml +++ b/.mise.toml @@ -32,9 +32,6 @@ ripgrep = "latest" [plugins] nnnn = 'https://github.com/mise-plugins/rtx-nodejs#main' -[alias.tiny] -abc = '1' - [task_config] includes = ["tasks"] diff --git a/docs/cli/alias.md b/docs/cli/alias.md index aa6a31260d..c781ce2a81 100644 --- a/docs/cli/alias.md +++ b/docs/cli/alias.md @@ -19,6 +19,6 @@ Don't show table header ## Subcommands - [`mise alias get `](/cli/alias/get.md) -- [`mise alias ls [--no-header] [PLUGIN]`](/cli/alias/ls.md) +- [`mise alias ls [--no-header] [TOOL]`](/cli/alias/ls.md) - [`mise alias set …`](/cli/alias/set.md) - [`mise alias unset `](/cli/alias/unset.md) diff --git a/docs/cli/alias/ls.md b/docs/cli/alias/ls.md index e1fe8787e3..37cd2efa83 100644 --- a/docs/cli/alias/ls.md +++ b/docs/cli/alias/ls.md @@ -1,6 +1,6 @@ # `mise alias ls` -- **Usage**: `mise alias ls [--no-header] [PLUGIN]` +- **Usage**: `mise alias ls [--no-header] [TOOL]` - **Aliases**: `list` - **Source code**: [`src/cli/alias/ls.rs`](https://github.com/jdx/mise/blob/main/src/cli/alias/ls.rs) @@ -10,14 +10,14 @@ These can come from user config or from plugins in `bin/list-aliases`. For user config, aliases are defined like the following in `~/.config/mise/config.toml`: - [alias.node] + [alias.node.versions] lts = "22.0.0" ## Arguments -### `[PLUGIN]` +### `[TOOL]` -Show aliases for <PLUGIN> +Show aliases for <TOOL> ## Flags diff --git a/docs/cli/index.md b/docs/cli/index.md index e32e65c787..5b48504407 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -31,7 +31,7 @@ Answer yes to all confirmation prompts - [`mise activate [--shims] [-q --quiet] [SHELL_TYPE]`](/cli/activate.md) - [`mise alias [-p --plugin ] [--no-header] `](/cli/alias.md) - [`mise alias get `](/cli/alias/get.md) -- [`mise alias ls [--no-header] [PLUGIN]`](/cli/alias/ls.md) +- [`mise alias ls [--no-header] [TOOL]`](/cli/alias/ls.md) - [`mise alias set …`](/cli/alias/set.md) - [`mise alias unset `](/cli/alias/unset.md) - [`mise backends `](/cli/backends.md) diff --git a/docs/configuration.md b/docs/configuration.md index 60fc487232..399487facb 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -44,7 +44,7 @@ node = ['16', 'prefix:20', 'ref:master', 'path:~/.nodes/14'] # note this will only be used if the plugin does not already exist python = 'https://github.com/asdf-community/asdf-python' -[alias.node] # project-local aliases +[alias.node.versions] # project-local aliases my_custom_node = '20' [tasks.build] diff --git a/docs/dev-tools/aliases.md b/docs/dev-tools/aliases.md index 5f0cc5cd43..74f339fc14 100644 --- a/docs/dev-tools/aliases.md +++ b/docs/dev-tools/aliases.md @@ -7,7 +7,7 @@ so you can use set it with `node lts-hydrogen` in `.tool-versions`/`mise.toml`. User aliases can be created by adding an `alias.` section to `~/.config/mise/config.toml`: ```toml -[alias.node] +[alias.node.versions] my_custom_20 = '20' ``` @@ -32,6 +32,6 @@ plugin currently, but plugin authors can add this script without impacting asdf Alias values can be templates, see [Templates](/templates) for details. ```toml -[alias.node] +[alias.node.versions] current = "{{exec(command='node --version')}}" ``` diff --git a/docs/mise.usage.kdl b/docs/mise.usage.kdl index 06c8e9d532..e4f28ea4b6 100644 --- a/docs/mise.usage.kdl +++ b/docs/mise.usage.kdl @@ -83,7 +83,7 @@ These can come from user config or from plugins in `bin/list-aliases`. For user config, aliases are defined like the following in `~/.config/mise/config.toml`: - [alias.node] + [alias.node.versions] lts = "20.0.0""# after_long_help r"Examples: diff --git a/docs/templates.md b/docs/templates.md index 1ae5e089db..a45d11d748 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -160,7 +160,7 @@ Mise offers additional functions: A example of function using `exec`: ```toml -[alias.node] +[alias.node.versions] current = "{{ exec(command='node --version') }}" ``` diff --git a/e2e/cli/test_alias b/e2e/cli/test_alias new file mode 100644 index 0000000000..fe4ac577f2 --- /dev/null +++ b/e2e/cli/test_alias @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +mise alias set tiny xxx 2 +assert_contains "mise alias ls tiny" "tiny xxx 2" +mise alias unset tiny xxx +assert_not_contains "mise alias ls" "tiny xxx" diff --git a/e2e/tools/test_tools_alias b/e2e/tools/test_tools_alias new file mode 100644 index 0000000000..24bf6d58c4 --- /dev/null +++ b/e2e/tools/test_tools_alias @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +cat <mise.toml +tools.mytool = "2" +tools.mytool-lts = "lts" + +alias.mytool = "asdf:tiny" +[alias.mytool-lts] +full = "asdf:tiny" +version = "1.0.1" +EOF + +assert "mise x mytool -- rtx-tiny" "2" +assert "mise x mytool-lts -- rtx-tiny" "1.0.1" diff --git a/mise.usage.kdl b/mise.usage.kdl index 00f2a1728b..f5ed5b2369 100644 --- a/mise.usage.kdl +++ b/mise.usage.kdl @@ -95,7 +95,7 @@ These can come from user config or from plugins in `bin/list-aliases`. For user config, aliases are defined like the following in `~/.config/mise/config.toml`: - [alias.node] + [alias.node.versions] lts = "22.0.0""# after_long_help r"Examples: @@ -103,7 +103,7 @@ For user config, aliases are defined like the following in `~/.config/mise/confi node lts-jod 22 " flag "--no-header" help="Don't show table header" - arg "[PLUGIN]" help="Show aliases for " + arg "[TOOL]" help="Show aliases for " } cmd "set" help="Add/update an alias for a plugin" { alias "add" "create" diff --git a/src/cli/alias/get.rs b/src/cli/alias/get.rs index 3559373200..1684cd28a8 100644 --- a/src/cli/alias/get.rs +++ b/src/cli/alias/get.rs @@ -20,7 +20,7 @@ impl AliasGet { pub fn run(self) -> Result<()> { let config = Config::try_get()?; match config.get_all_aliases().get(&self.plugin) { - Some(plugin) => match plugin.get(&self.alias) { + Some(alias) => match alias.versions.get(&self.alias) { Some(alias) => { miseprintln!("{alias}"); Ok(()) diff --git a/src/cli/alias/ls.rs b/src/cli/alias/ls.rs index 3da0997687..1d880047b1 100644 --- a/src/cli/alias/ls.rs +++ b/src/cli/alias/ls.rs @@ -1,4 +1,5 @@ use eyre::Result; +use itertools::Itertools; use tabled::Tabled; use crate::cli::args::BackendArg; @@ -11,14 +12,14 @@ use crate::ui::table; /// /// For user config, aliases are defined like the following in `~/.config/mise/config.toml`: /// -/// [alias.node] +/// [alias.node.versions] /// lts = "22.0.0" #[derive(Debug, clap::Args)] #[clap(visible_alias = "list", after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)] pub struct AliasLs { - /// Show aliases for + /// Show aliases for #[clap()] - pub plugin: Option, + pub tool: Option, /// Don't show table header #[clap(long)] @@ -31,15 +32,15 @@ impl AliasLs { let rows = config .get_all_aliases() .iter() - .filter(|(fa, _)| { - self.plugin.is_none() || self.plugin.as_ref().is_some_and(|f| &f == fa) - }) + .filter(|(fa, _)| self.tool.is_none() || self.tool.as_ref().is_some_and(|f| &f == fa)) + .sorted_by(|(a, _), (b, _)| a.name.cmp(&b.name)) .flat_map(|(fa, aliases)| { aliases + .versions .iter() .filter(|(from, _to)| fa.name != "node" || !from.starts_with("lts/")) .map(|(from, to)| Row { - plugin: fa.to_string(), + tool: fa.to_string(), alias: from.clone(), version: to.clone(), }) @@ -55,7 +56,7 @@ impl AliasLs { #[derive(Tabled)] struct Row { - plugin: String, + tool: String, alias: String, version: String, } @@ -67,41 +68,3 @@ static AFTER_LONG_HELP: &str = color_print::cstr!( node lts-jod 22 "# ); - -#[cfg(test)] -mod tests { - use crate::test::reset; - use test_log::test; - - #[test] - fn test_alias_ls() { - reset(); - assert_cli_snapshot!("aliases", @r" - java lts 21 - node lts 22 - node lts-argon 4 - node lts-boron 6 - node lts-carbon 8 - node lts-dubnium 10 - node lts-erbium 12 - node lts-fermium 14 - node lts-gallium 16 - node lts-hydrogen 18 - node lts-iron 20 - node lts-jod 22 - tiny lts 3.1.0 - tiny lts-prev 2.0.0 - tiny my/alias 3.0 - "); - } - - #[test] - fn test_alias_ls_filter() { - reset(); - assert_cli_snapshot!("aliases", "ls", "tiny", @r" - tiny lts 3.1.0 - tiny lts-prev 2.0.0 - tiny my/alias 3.0 - "); - } -} diff --git a/src/cli/alias/mod.rs b/src/cli/alias/mod.rs index a68901726e..452446a388 100644 --- a/src/cli/alias/mod.rs +++ b/src/cli/alias/mod.rs @@ -45,7 +45,7 @@ impl Commands { impl Alias { pub fn run(self) -> Result<()> { let cmd = self.command.unwrap_or(Commands::Ls(ls::AliasLs { - plugin: self.plugin, + tool: self.plugin, no_header: self.no_header, })); diff --git a/src/cli/alias/set.rs b/src/cli/alias/set.rs index 59a9eb2aa5..fb22a82a7d 100644 --- a/src/cli/alias/set.rs +++ b/src/cli/alias/set.rs @@ -32,33 +32,3 @@ static AFTER_LONG_HELP: &str = color_print::cstr!( $ mise alias set node lts-jod 22.0.0 "# ); - -#[cfg(test)] -pub mod tests { - use crate::test::reset; - - #[test] - fn test_alias_set() { - reset(); - assert_cli!("alias", "set", "tiny", "my/alias", "3.0"); - - assert_cli_snapshot!("aliases", @r" - java lts 21 - node lts 22 - node lts-argon 4 - node lts-boron 6 - node lts-carbon 8 - node lts-dubnium 10 - node lts-erbium 12 - node lts-fermium 14 - node lts-gallium 16 - node lts-hydrogen 18 - node lts-iron 20 - node lts-jod 22 - tiny lts 3.1.0 - tiny lts-prev 2.0.0 - tiny my/alias 3.0 - "); - reset(); - } -} diff --git a/src/cli/alias/unset.rs b/src/cli/alias/unset.rs index 0e7b4eac43..d9de69719f 100644 --- a/src/cli/alias/unset.rs +++ b/src/cli/alias/unset.rs @@ -30,33 +30,3 @@ static AFTER_LONG_HELP: &str = color_print::cstr!( $ mise alias unset node lts-jod "# ); - -#[cfg(test)] -mod tests { - use crate::test::reset; - - #[test] - fn test_alias_unset() { - reset(); - - assert_cli!("alias", "unset", "tiny", "my/alias"); - assert_cli_snapshot!("aliases", @r" - java lts 21 - node lts 22 - node lts-argon 4 - node lts-boron 6 - node lts-carbon 8 - node lts-dubnium 10 - node lts-erbium 12 - node lts-fermium 14 - node lts-gallium 16 - node lts-hydrogen 18 - node lts-iron 20 - node lts-jod 22 - tiny lts 3.1.0 - tiny lts-prev 2.0.0 - "); - - reset(); - } -} diff --git a/src/cli/config/generate.rs b/src/cli/config/generate.rs index a70b1e41ba..c5eb96d2d8 100644 --- a/src/cli/config/generate.rs +++ b/src/cli/config/generate.rs @@ -67,7 +67,7 @@ impl ConfigGenerate { # # note this will only be used if the plugin is not already installed # python = 'https://github.com/asdf-community/asdf-python' # -# [alias.node] +# [alias.node.versions] # # setup a custom alias so you can run `mise use -g node@work` for node-16.x # work = '16' "# diff --git a/src/cli/config/snapshots/mise__cli__config__generate__tests__generate.snap b/src/cli/config/snapshots/mise__cli__config__generate__tests__generate.snap index 707dba63ea..d185bce60b 100644 --- a/src/cli/config/snapshots/mise__cli__config__generate__tests__generate.snap +++ b/src/cli/config/snapshots/mise__cli__config__generate__tests__generate.snap @@ -49,6 +49,6 @@ snapshot_kind: text # # note this will only be used if the plugin is not already installed # python = 'https://github.com/asdf-community/asdf-python' # -# [alias.node] +# [alias.node.versions] # # setup a custom alias so you can run `mise use -g node@work` for node-16.x # work = '16' diff --git a/src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap b/src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap index f6e33dd801..9fcb1c2127 100644 --- a/src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap +++ b/src/cli/config/snapshots/mise__cli__config__get__tests__toml_get.snap @@ -3,7 +3,7 @@ source: src/cli/config/get.rs expression: output snapshot_kind: text --- -[alias.tiny] +[alias.tiny.versions] "my/alias" = "3.0" [env] diff --git a/src/config/config_file/mise_toml.rs b/src/config/config_file/mise_toml.rs index 3e643fef64..45a5ed1161 100644 --- a/src/config/config_file/mise_toml.rs +++ b/src/config/config_file/mise_toml.rs @@ -18,7 +18,7 @@ use crate::config::config_file::toml::{deserialize_arr, deserialize_path_entry_a use crate::config::config_file::{trust_check, ConfigFile, TaskConfig}; use crate::config::env_directive::{EnvDirective, PathEntry}; use crate::config::settings::SettingsPartial; -use crate::config::AliasMap; +use crate::config::{Alias, AliasMap}; use crate::file::{create_dir_all, display_path}; use crate::registry::REGISTRY_BACKEND_MAP; use crate::task::Task; @@ -40,7 +40,7 @@ pub struct MiseToml { env: EnvList, #[serde(default, deserialize_with = "deserialize_arr")] env_path: Vec, - #[serde(default, deserialize_with = "deserialize_alias")] + #[serde(default)] alias: AliasMap, #[serde(skip)] doc: OnceCell, @@ -122,6 +122,7 @@ impl MiseToml { self.alias .entry(fa.clone()) .or_default() + .versions .insert(from.into(), to.into()); self.doc_mut()? .entry("alias") @@ -132,6 +133,10 @@ impl MiseToml { .or_insert_with(table) .as_table_like_mut() .unwrap() + .entry("versions") + .or_insert_with(table) + .as_table_like_mut() + .unwrap() .insert(from, value(to)); Ok(()) } @@ -142,12 +147,17 @@ impl MiseToml { .get_mut("alias") .and_then(|v| v.as_table_mut()) { - if let Some(plugin_aliases) = aliases + if let Some(alias) = aliases .get_mut(&fa.to_string()) .and_then(|v| v.as_table_mut()) { - plugin_aliases.remove(from); - if plugin_aliases.is_empty() { + if let Some(versions) = alias.get_mut("versions").and_then(|v| v.as_table_mut()) { + versions.remove(from); + if versions.is_empty() { + alias.remove("versions"); + } + } + if alias.is_empty() { aliases.remove(&fa.to_string()); } } @@ -156,9 +166,9 @@ impl MiseToml { } } if let Some(aliases) = self.alias.get_mut(fa) { - aliases.remove(from); - if aliases.is_empty() { - self.alias.remove(fa); + aliases.versions.swap_remove(from); + if aliases.versions.is_empty() && aliases.full.is_none() { + self.alias.swap_remove(fa); } } Ok(()) @@ -395,16 +405,22 @@ impl ConfigFile for MiseToml { .clone() .iter() .map(|(k, v)| { - let k = k.clone(); - let v: Result, eyre::Error> = v + let versions = v .clone() + .versions .into_iter() .map(|(k, v)| { let v = self.parse_template(&v)?; - Ok((k, v)) + Ok::<(String, String), eyre::Report>((k, v)) }) - .collect(); - v.map(|v| (k, v)) + .collect::>>()?; + Ok(( + k.clone(), + Alias { + full: v.full.clone(), + versions, + }, + )) }) .collect() } @@ -919,35 +935,55 @@ impl<'de> de::Deserialize<'de> for BackendArg { } } -fn deserialize_alias<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - struct AliasMapVisitor; +impl<'de> de::Deserialize<'de> for Alias { + fn deserialize(deserializer: D) -> std::result::Result + where + D: de::Deserializer<'de>, + { + struct AliasVisitor; - impl<'de> Visitor<'de> for AliasMapVisitor { - type Value = AliasMap; - fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { - formatter.write_str("alias table") - } + impl<'de> Visitor<'de> for AliasVisitor { + type Value = Alias; + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + formatter.write_str("alias") + } - fn visit_map(self, mut map: M) -> std::result::Result - where - M: de::MapAccess<'de>, - { - let mut aliases = AliasMap::new(); - while let Some(plugin) = map.next_key::()? { - let fa: BackendArg = plugin.as_str().into(); - let plugin_aliases = aliases.entry(fa).or_default(); - for (from, to) in map.next_value::>()? { - plugin_aliases.insert(from, to); + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Ok(Alias { + full: Some(v.to_string()), + ..Default::default() + }) + } + + fn visit_map(self, mut map: M) -> Result + where + M: de::MapAccess<'de>, + { + let mut full = None; + let mut versions = IndexMap::new(); + while let Some(key) = map.next_key::()? { + match key.as_str() { + "full" => { + full = Some(map.next_value()?); + } + "versions" => { + versions = map.next_value()?; + } + _ => { + deprecated!("TOOL_VERSION_ALIASES", "tool version aliases should be `alias..versions. = `, not `alias.. = `"); + versions.insert(key, map.next_value()?); + } + } } + Ok(Alias { full, versions }) } - Ok(aliases) } - } - deserializer.deserialize_map(AliasMapVisitor) + deserializer.deserialize_any(AliasVisitor) + } } #[cfg(test)] @@ -1127,7 +1163,7 @@ mod tests { file::write( &p, formatdoc! {r#" - [alias.node] + [alias.node.versions] 16 = "16.0.0" 18 = "18.0.0" "#}, @@ -1153,11 +1189,11 @@ mod tests { file::write( &p, formatdoc! {r#" - [alias.node] + [alias.node.versions] 16 = "16.0.0" 18 = "18.0.0" - [alias.python] + [alias.python.versions] "3.10" = "3.10.0" "#}, ) diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-4.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-4.snap index b1f0ef4bbf..eb35398901 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-4.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-4.snap @@ -4,7 +4,10 @@ expression: cf.alias snapshot_kind: text --- { - BackendArg("node"): { - "my_custom_node": "18", + BackendArg("node"): Alias { + full: None, + versions: { + "my_custom_node": "18", + }, }, } diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-5.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-5.snap index 8b66ab299d..2cc4924770 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-5.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__fixture-5.snap @@ -12,8 +12,11 @@ MiseToml(~/fixtures/.mise.toml): ToolRequestSet: terraform@1.0.0 node@18 node@pr ), ], alias: { - BackendArg("node"): { - "my_custom_node": "18", + BackendArg("node"): Alias { + full: None, + versions: { + "my_custom_node": "18", + }, }, }, plugins: { diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-2.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-2.snap index 736adfee8e..3adcb11d85 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-2.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-2.snap @@ -3,5 +3,5 @@ source: src/config/config_file/mise_toml.rs expression: cf.dump().unwrap() snapshot_kind: text --- -[alias.node] +[alias.node.versions] 18 = "18.0.0" diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-4.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-4.snap index f8143a37b6..bcc1d55fce 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-4.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias-4.snap @@ -6,8 +6,11 @@ snapshot_kind: text MiseToml(~/cwd/.test.mise.toml): ToolRequestSet: { alias: { - BackendArg("node"): { - "18": "18.0.0", + BackendArg("node"): Alias { + full: None, + versions: { + "18": "18.0.0", + }, }, }, } diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias.snap index c803be7590..f1657bef06 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__remove_alias.snap @@ -4,7 +4,10 @@ expression: cf.alias snapshot_kind: text --- { - BackendArg("node"): { - "18": "18.0.0", + BackendArg("node"): Alias { + full: None, + versions: { + "18": "18.0.0", + }, }, } diff --git a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__set_alias.snap b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__set_alias.snap index 12ed7ce562..0fd42d014e 100644 --- a/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__set_alias.snap +++ b/src/config/config_file/snapshots/mise__config__config_file__mise_toml__tests__set_alias.snap @@ -4,12 +4,18 @@ expression: cf.alias snapshot_kind: text --- { - BackendArg("node"): { - "16": "16.0.0", - "18": "18.0.1", - "20": "20.0.0", + BackendArg("node"): Alias { + full: None, + versions: { + "16": "16.0.0", + "18": "18.0.1", + "20": "20.0.0", + }, }, - BackendArg("python"): { - "3.10": "3.10.0", + BackendArg("python"): Alias { + full: None, + versions: { + "3.10": "3.10.0", + }, }, } diff --git a/src/config/mod.rs b/src/config/mod.rs index 6b08224600..5c194448b5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -34,7 +34,7 @@ pub mod tracking; pub use settings::SETTINGS; -type AliasMap = BTreeMap>; +type AliasMap = IndexMap; type ConfigMap = IndexMap>; type EnvWithSources = IndexMap; @@ -52,6 +52,12 @@ pub struct Config { tool_request_set: OnceCell, } +#[derive(Debug, Clone, Default)] +pub struct Alias { + pub full: Option, + pub versions: IndexMap, +} + pub static CONFIG: Lazy> = Lazy::new(Config::get); static _CONFIG: RwLock>> = RwLock::new(None); @@ -188,7 +194,7 @@ impl Config { pub fn resolve_alias(&self, backend: &ABackend, v: &str) -> Result { if let Some(plugin_aliases) = self.aliases.get(backend.fa()) { - if let Some(alias) = plugin_aliases.get(v) { + if let Some(alias) = plugin_aliases.versions.get(v) { return Ok(alias.clone()); } } @@ -212,15 +218,20 @@ impl Config { .collect(); for (fa, plugin_aliases) in plugin_aliases { for (from, to) in plugin_aliases { - aliases.entry(fa.clone()).or_default().insert(from, to); + aliases + .entry(fa.clone()) + .or_default() + .versions + .insert(from, to); } } for (plugin, plugin_aliases) in &self.aliases { - for (from, to) in plugin_aliases { + for (from, to) in &plugin_aliases.versions { aliases .entry(plugin.clone()) .or_default() + .versions .insert(from.clone(), to.clone()); } } @@ -733,8 +744,12 @@ fn load_aliases(config_files: &ConfigMap) -> Result { for config_file in config_files.values() { for (plugin, plugin_aliases) in config_file.aliases()? { - for (from, to) in plugin_aliases { - aliases.entry(plugin.clone()).or_default().insert(from, to); + for (from, to) in plugin_aliases.versions { + aliases + .entry(plugin.clone()) + .or_default() + .versions + .insert(from, to); } } } diff --git a/src/config/snapshots/mise__config__tests__load.snap b/src/config/snapshots/mise__config__tests__load.snap index dba520615f..bca23d568f 100644 --- a/src/config/snapshots/mise__config__tests__load.snap +++ b/src/config/snapshots/mise__config__tests__load.snap @@ -10,8 +10,11 @@ Config { "~/config/config.toml", ], Aliases: { - BackendArg("tiny"): { - "my/alias": "3.0", + BackendArg("tiny"): Alias { + full: None, + versions: { + "my/alias": "3.0", + }, }, }, } diff --git a/src/output.rs b/src/output.rs index eaeb6042b2..5a8ea4fa7c 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,5 +1,8 @@ #[cfg(feature = "timings")] use crate::ui::style; +use once_cell::sync::Lazy; +use std::collections::HashSet; +use std::sync::Mutex; #[cfg(test)] #[macro_export] @@ -193,6 +196,17 @@ macro_rules! error { }}; } +pub static DEPRECATED: Lazy>> = Lazy::new(Default::default); + +#[macro_export] +macro_rules! deprecated { + ($id:tt, $($arg:tt)*) => {{ + if $crate::output::DEPRECATED.lock().unwrap().insert($id) { + warn!("deprecated [{}]: {}", $id, format!($($arg)*)); + } + }}; +} + #[cfg(test)] pub mod tests { use std::sync::Mutex; diff --git a/src/runtime_symlinks.rs b/src/runtime_symlinks.rs index ca613a7c9a..9f1aaed42d 100644 --- a/src/runtime_symlinks.rs +++ b/src/runtime_symlinks.rs @@ -1,9 +1,8 @@ -use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use std::sync::Arc; use crate::backend::{backend_meta, Backend}; -use crate::config::Config; +use crate::config::{Alias, Config}; use crate::file::make_symlink_or_file; use crate::plugins::VERSION_REGEX; use crate::{backend, file}; @@ -59,10 +58,11 @@ fn list_symlinks(config: &Config, backend: Arc) -> Result