Skip to content

Commit

Permalink
feat: added backend aliases
Browse files Browse the repository at this point in the history
Fixes #2885
  • Loading branch information
jdx committed Nov 10, 2024
1 parent 3aa3250 commit f3af8b1
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 45 deletions.
14 changes: 14 additions & 0 deletions e2e/tools/test_tools_alias
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

cat <<EOF >mise.toml
tools.xxx21 = "2"
tools.xxxlts = "lts"
alias.xxx21 = "asdf:tiny"
[alias.xxxlts]
full = "asdf:tiny"
version = "1.0.1"
EOF

assert "mise x xxx21 -- rtx-tiny" "2"
assert "mise x xxxlts -- rtx-tiny" "2"
2 changes: 1 addition & 1 deletion src/cli/alias/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down
1 change: 1 addition & 0 deletions src/cli/alias/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl AliasLs {
})
.flat_map(|(fa, aliases)| {
aliases
.versions
.iter()
.filter(|(from, _to)| fa.name != "node" || !from.starts_with("lts/"))
.map(|(from, to)| Row {
Expand Down
95 changes: 61 additions & 34 deletions src/config/config_file/mise_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use eyre::{eyre, WrapErr};
use indexmap::IndexMap;
use itertools::Itertools;
use once_cell::sync::OnceCell;
use serde::de::Visitor;
use serde::de::{Visitor};
use serde::{de, Deserializer};
use serde_derive::Deserialize;
use tera::Context as TeraContext;
Expand All @@ -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::task::Task;
use crate::tera::{get_tera, BASE_CONTEXT};
Expand All @@ -39,7 +39,7 @@ pub struct MiseToml {
env: EnvList,
#[serde(default, deserialize_with = "deserialize_arr")]
env_path: Vec<PathEntry>,
#[serde(default, deserialize_with = "deserialize_alias")]
#[serde(default)]
alias: AliasMap,
#[serde(skip)]
doc: OnceCell<DocumentMut>,
Expand Down Expand Up @@ -121,6 +121,7 @@ impl MiseToml {
self.alias
.entry(fa.clone())
.or_default()
.versions
.insert(from.into(), to.into());
self.doc_mut()?
.entry("alias")
Expand Down Expand Up @@ -155,9 +156,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() {
self.alias.swap_remove(fa);
}
}
Ok(())
Expand Down Expand Up @@ -382,16 +383,19 @@ impl ConfigFile for MiseToml {
.clone()
.iter()
.map(|(k, v)| {
let k = k.clone();
let v: Result<BTreeMap<String, String>, 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::<eyre::Result<IndexMap<_, _>>>()?;
Ok((k.clone(), Alias{
full: v.full.clone(),
versions,
}))
})
.collect()
}
Expand Down Expand Up @@ -906,35 +910,58 @@ impl<'de> de::Deserialize<'de> for BackendArg {
}
}

fn deserialize_alias<'de, D>(deserializer: D) -> Result<AliasMap, D::Error>
where
D: Deserializer<'de>,
{
struct AliasMapVisitor;
impl<'de> de::Deserialize<'de> for Alias {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
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<M>(self, mut map: M) -> std::result::Result<Self::Value, M::Error>
where
M: de::MapAccess<'de>,
{
let mut aliases = AliasMap::new();
while let Some(plugin) = map.next_key::<String>()? {
let fa: BackendArg = plugin.as_str().into();
let plugin_aliases = aliases.entry(fa).or_default();
for (from, to) in map.next_value::<BTreeMap<String, String>>()? {
plugin_aliases.insert(from, to);
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Alias{
full: Some(v.to_string()),
..Default::default()
})
}

fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
where
M: de::MapAccess<'de>,
{
let mut full = None;
let mut versions = IndexMap::new();
while let Some(key) = map.next_key::<String>()? {
match key.as_str() {
"full" => {
full = Some(map.next_value()?);
}
"versions" => {
versions = map.next_value()?;
}
_ => {
warn!("deprecated: tool version aliases should now be nested in `alias.<TOOL>.versions.<FROM> = <TO>`");
versions.insert(key, map.next_value()?);
}
}
}
Ok(Alias{
full,
versions,
})
}
Ok(aliases)
}
}

deserializer.deserialize_map(AliasMapVisitor)
deserializer.deserialize_any(AliasVisitor)
}
}

#[cfg(test)]
Expand Down
23 changes: 17 additions & 6 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub mod tracking;

pub use settings::SETTINGS;

type AliasMap = BTreeMap<BackendArg, BTreeMap<String, String>>;
type AliasMap = IndexMap<BackendArg, Alias>;
type ConfigMap = IndexMap<PathBuf, Box<dyn ConfigFile>>;
type EnvWithSources = IndexMap<String, (String, PathBuf)>;

Expand All @@ -52,6 +52,12 @@ pub struct Config {
tool_request_set: OnceCell<ToolRequestSet>,
}

#[derive(Debug, Clone, Default)]
pub struct Alias {
pub full: Option<String>,
pub versions: IndexMap<String, String>,
}

pub static CONFIG: Lazy<Arc<Config>> = Lazy::new(Config::get);
static _CONFIG: RwLock<Option<Arc<Config>>> = RwLock::new(None);

Expand Down Expand Up @@ -188,7 +194,7 @@ impl Config {

pub fn resolve_alias(&self, backend: &ABackend, v: &str) -> Result<String> {
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());
}
}
Expand All @@ -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());
}
}
Expand Down Expand Up @@ -733,8 +744,8 @@ fn load_aliases(config_files: &ConfigMap) -> Result<AliasMap> {

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);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/runtime_symlinks.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -59,10 +58,11 @@ fn list_symlinks(config: &Config, backend: Arc<dyn Backend>) -> Result<IndexMap<
symlinks.insert(from, rel_path(&v));
}
symlinks.insert(format!("{prefix}latest"), rel_path(&v));
for (from, to) in config
for (from, to) in &config
.get_all_aliases()
.get(backend.fa())
.unwrap_or(&BTreeMap::new())
.unwrap_or(&Alias::default())
.versions
{
if from.contains('/') {
continue;
Expand Down

0 comments on commit f3af8b1

Please sign in to comment.