From 03e99ef22d1c989e23bc6e63ebb1950cfc277cff Mon Sep 17 00:00:00 2001 From: Taku Kodma <79110363+risu729@users.noreply.github.com> Date: Tue, 5 May 2026 18:50:52 +1000 Subject: [PATCH] fix(backend): reject bare package backend names --- e2e/backend/test_bare_backend_names | 4 ++++ src/cli/args/backend_arg.rs | 26 ++++++++++++++++++++++++-- src/toolset/install_state.rs | 5 ++++- 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 e2e/backend/test_bare_backend_names diff --git a/e2e/backend/test_bare_backend_names b/e2e/backend/test_bare_backend_names new file mode 100644 index 0000000000..62abea7f9b --- /dev/null +++ b/e2e/backend/test_bare_backend_names @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +assert_fail "mise install cargo" "cargo not found in mise tool registry" +assert_fail "mise install gem" "gem not found in mise tool registry" diff --git a/src/cli/args/backend_arg.rs b/src/cli/args/backend_arg.rs index de507ce756..f70369c068 100644 --- a/src/cli/args/backend_arg.rs +++ b/src/cli/args/backend_arg.rs @@ -314,8 +314,9 @@ impl BackendArg { } let full = self.full(); - let backend = full.split(':').next().unwrap(); - if let Ok(backend_type) = backend.parse() { + if let Some((backend, _)) = full.split_once(':') + && let Ok(backend_type) = backend.parse() + { return backend_type; } if config::is_loaded() && Config::get_().get_repo_url(&self.short).is_some() { @@ -648,6 +649,27 @@ mod tests { ); } + #[tokio::test] + async fn test_bare_package_backend_names_are_not_implicit_tools() { + let _config = Config::get().await.unwrap(); + + for name in ["cargo", "gem"] { + let fa: BackendArg = name.into(); + assert_str_eq!(name, fa.full()); + assert_eq!(BackendType::Unknown, fa.backend_type()); + } + + let fa: BackendArg = "cargo:ripgrep".into(); + assert_eq!(BackendType::Cargo, fa.backend_type()); + + let fa: BackendArg = "gem:bashly".into(); + assert_eq!(BackendType::Gem, fa.backend_type()); + + let fa: BackendArg = "npm".into(); + assert_str_eq!("npm:npm", fa.full()); + assert_eq!(BackendType::Npm, fa.backend_type()); + } + #[tokio::test] async fn test_backend_arg_pathname() { let _config = Config::get().await.unwrap(); diff --git a/src/toolset/install_state.rs b/src/toolset/install_state.rs index 3b3dfb7d42..cb8f878d2f 100644 --- a/src/toolset/install_state.rs +++ b/src/toolset/install_state.rs @@ -441,7 +441,10 @@ pub fn backend_type(short: &str) -> Result> { let backend_type = list_tools() .get(short) .and_then(|ist| ist.full.as_ref()) - .map(|full| BackendType::guess(full)); + .and_then(|full| { + full.split_once(':') + .map(|(backend, _)| BackendType::guess(backend)) + }); if let Some(BackendType::Unknown) = backend_type && let Some((plugin_name, _)) = short.split_once(':') && let Some(PluginType::VfoxBackend) = get_plugin_type(plugin_name)