diff --git a/build.rs b/build.rs index c22f9c9a3f..44c247cc41 100644 --- a/build.rs +++ b/build.rs @@ -135,7 +135,26 @@ fn codegen_registry() { .and_then(|v| v.as_str()) .unwrap_or_else(|| panic!("[{short}] 'test.expected' must be a string")) .to_string(); - (cmd, expected) + let tools = t + .get("tools") + .map(|tools| { + let mut tools = tools + .as_array() + .unwrap_or_else(|| panic!("[{short}] 'test.tools' must be an array")) + .iter() + .map(|v| { + v.as_str() + .unwrap_or_else(|| { + panic!("[{short}] 'test.tools' must contain only strings") + }) + .to_string() + }) + .collect::>(); + tools.sort(); + tools + }) + .unwrap_or_default(); + (cmd, expected, tools) }); let mut backends = vec![]; for backend in info.get("backends").unwrap().as_array().unwrap() { @@ -202,18 +221,6 @@ fn codegen_registry() { let description = info .get("description") .map(|d| d.as_str().unwrap().to_string()); - let depends = info - .get("depends") - .map(|depends| { - let depends = depends.as_array().unwrap(); - let mut depends = depends - .iter() - .map(|d| d.as_str().unwrap().to_string()) - .collect::>(); - depends.sort(); - depends - }) - .unwrap_or_default(); let idiomatic_files = info .get("idiomatic_files") .map(|idiomatic_files| { @@ -248,7 +255,7 @@ fn codegen_registry() { }) .unwrap_or_default(); let rt = format!( - r#"RegistryTool{{short: "{short}", description: {description}, backends: &[{backends}], aliases: &[{aliases}], test: &{test}, os: &[{os}], depends: &[{depends}], idiomatic_files: &[{idiomatic_files}], detect: &[{detect}], overrides: &[{overrides}]}}"#, + r#"RegistryTool{{short: "{short}", description: {description}, backends: &[{backends}], aliases: &[{aliases}], test: &{test}, os: &[{os}], idiomatic_files: &[{idiomatic_files}], detect: &[{detect}], overrides: &[{overrides}]}}"#, description = description .map(|d| format!("Some({})", raw_string_literal(&d))) .unwrap_or("None".to_string()), @@ -259,10 +266,15 @@ fn codegen_registry() { .collect::>() .join(", "), test = test - .map(|(t, v)| format!( - "Some(({}, {}))", - raw_string_literal(&t), - raw_string_literal(&v) + .map(|(cmd, expected, tools)| format!( + "Some(RegistryToolTest{{ cmd: {}, expected: {}, tools: &[{}] }})", + raw_string_literal(&cmd), + raw_string_literal(&expected), + tools + .iter() + .map(|tool| format!("\"{tool}\"")) + .collect::>() + .join(", ") )) .unwrap_or("None".to_string()), os = os @@ -270,11 +282,6 @@ fn codegen_registry() { .map(|o| format!("\"{o}\"")) .collect::>() .join(", "), - depends = depends - .iter() - .map(|d| format!("\"{d}\"")) - .collect::>() - .join(", "), idiomatic_files = idiomatic_files .iter() .map(|f| format!("\"{f}\"")) diff --git a/docs/contributing.md b/docs/contributing.md index 31c5c4b07e..9f4076b86b 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -704,15 +704,20 @@ backend, but can override with explicit syntax like `mise use aqua:owner/repo`. All tools must include a test to verify proper installation: ```toml -test = [ - "command-to-run", - "expected-output-pattern" -] +test = { cmd = "command-to-run", expected = "expected-output-pattern" } ``` The test command should be reliable and the output pattern should use {{version}} to match any version number. +If `test.cmd` needs extra mise-managed tools on PATH, declare them with +`test.tools`. This is used only by `mise test-tool`; it does not affect normal +tool installation. + +```toml +test = { cmd = "gradle -V", expected = "Gradle", tools = ["java"] } +``` + ### Registry Examples Recent tool additions: diff --git a/registry/android-sdk.toml b/registry/android-sdk.toml index d20d2fb791..ffe14d6a49 100644 --- a/registry/android-sdk.toml +++ b/registry/android-sdk.toml @@ -1,4 +1,3 @@ backends = ["vfox:mise-plugins/vfox-android-sdk"] -depends = ["java"] description = "Android Command-line tools" -test = { cmd = "sdkmanager --version", expected = ".0" } +test = { cmd = "sdkmanager --version", expected = ".0", tools = ["java"] } diff --git a/registry/elixir.toml b/registry/elixir.toml index 9fa70255d4..5fb6d482c7 100644 --- a/registry/elixir.toml +++ b/registry/elixir.toml @@ -1,3 +1,2 @@ backends = ["core:elixir"] -depends = ["erlang"] description = "Elixir is a dynamic, functional language for building scalable and maintainable applications" diff --git a/registry/google-java-format.toml b/registry/google-java-format.toml index ebea6e8440..193a93b28a 100644 --- a/registry/google-java-format.toml +++ b/registry/google-java-format.toml @@ -1,4 +1,3 @@ backends = ["aqua:google/google-java-format"] -depends = ["java"] description = "Reformats Java source code to comply with Google Java Style" test = { cmd = "google-java-format --version", expected = "google-java-format: Version {{version}}" } diff --git a/registry/gradle.toml b/registry/gradle.toml index 3f46c9c19a..b9902280ac 100644 --- a/registry/gradle.toml +++ b/registry/gradle.toml @@ -1,4 +1,3 @@ backends = ["aqua:gradle/gradle", "vfox:mise-plugins/vfox-gradle"] -depends = ["java"] description = "Gradle is the open source build system of choice for Java, Android, and Kotlin developers" -test = { cmd = "gradle -V", expected = "Gradle" } +test = { cmd = "gradle -V", expected = "Gradle", tools = ["java"] } diff --git a/registry/kscript.toml b/registry/kscript.toml index f56f03ae57..03fd70b087 100644 --- a/registry/kscript.toml +++ b/registry/kscript.toml @@ -1,4 +1,5 @@ backends = ["github:kscripting/kscript", "asdf:edgelevel/asdf-kscript"] -depends = ["kotlin"] description = "Scripting enhancements for Kotlin" -test = { cmd = "kscript --version", expected = "Version : {{version}}" } +test = { cmd = "kscript --version", expected = "Version : {{version}}", tools = [ + "kotlin", +] } diff --git a/registry/ktlint.toml b/registry/ktlint.toml index dbfb98e739..caded7ff9f 100644 --- a/registry/ktlint.toml +++ b/registry/ktlint.toml @@ -1,4 +1,3 @@ backends = ["aqua:pinterest/ktlint", "asdf:mise-plugins/mise-ktlint"] -depends = ["java"] description = "An anti-bikeshedding Kotlin linter with built-in formatter" # test = ["ktlint --version", "ktlint version {{version}}"] # DISABLED: upstream bug - release 1.7.2 not found on GitHub diff --git a/registry/kubecolor.toml b/registry/kubecolor.toml index 795da39034..0664dd63e4 100644 --- a/registry/kubecolor.toml +++ b/registry/kubecolor.toml @@ -1,4 +1,3 @@ backends = ["aqua:kubecolor/kubecolor", "asdf:dex4er/asdf-kubecolor"] -depends = ["kubectl"] description = "Colorize your kubectl output" test = { cmd = "kubecolor --kubecolor-version", expected = "{{version}}" } diff --git a/registry/pipenv.toml b/registry/pipenv.toml index 79ac839b1c..44fa867f10 100644 --- a/registry/pipenv.toml +++ b/registry/pipenv.toml @@ -1,4 +1,5 @@ backends = ["vfox:mise-plugins/vfox-pipenv", "pipx:pipenv"] -depends = ["python"] description = "Python Development Workflow for Humans" -test = { cmd = "pipenv --version", expected = "pipenv, version {{version}}" } +test = { cmd = "pipenv --version", expected = "pipenv, version {{version}}", tools = [ + "python", +] } diff --git a/registry/pipx.toml b/registry/pipx.toml index 3fcaa41fd6..f3db261fa8 100644 --- a/registry/pipx.toml +++ b/registry/pipx.toml @@ -1,3 +1,2 @@ backends = ["aqua:pypa/pipx", "asdf:mise-plugins/mise-pipx"] -depends = ["python"] -test = { cmd = "pipx --version", expected = "{{version}}" } +test = { cmd = "pipx --version", expected = "{{version}}", tools = ["python"] } diff --git a/registry/rebar.toml b/registry/rebar.toml index 3c345d881d..6c4a35b1b1 100644 --- a/registry/rebar.toml +++ b/registry/rebar.toml @@ -1,6 +1,7 @@ backends = [ { full = "github:erlang/rebar3", options = { asset_pattern = "rebar3" } }, ] -depends = ["erlang"] description = "Erlang build tool that makes it easy to compile and test Erlang applications and releases" -test = { cmd = "rebar3 --version", expected = "rebar {{version}}" } +test = { cmd = "rebar3 --version", expected = "rebar {{version}}", tools = [ + "erlang", +] } diff --git a/registry/sbt.toml b/registry/sbt.toml index 9d08e47e72..e44500bbe7 100644 --- a/registry/sbt.toml +++ b/registry/sbt.toml @@ -1,4 +1,3 @@ backends = ["conda:sbt", "asdf:mise-plugins/mise-sbt"] -depends = ["java"] description = "sbt, the interactive build tool" test = { cmd = "sbt --version", expected = "sbt" } diff --git a/registry/spark.toml b/registry/spark.toml index 5604c363c5..71a3a7a776 100644 --- a/registry/spark.toml +++ b/registry/spark.toml @@ -1,3 +1,2 @@ backends = ["aqua:apache/spark", "asdf:mise-plugins/mise-spark"] -depends = ["java"] description = "Apache Spark - A unified analytics engine for large-scale data processing" diff --git a/registry/tridentctl.toml b/registry/tridentctl.toml index 65223671a2..5147f67589 100644 --- a/registry/tridentctl.toml +++ b/registry/tridentctl.toml @@ -2,7 +2,6 @@ backends = [ "aqua:NetApp/trident/tridentctl", "asdf:asdf-community/asdf-tridentctl", ] -depends = ["kubectl"] description = "Storage orchestrator for containers" os = ["linux", "macos"] test = { cmd = "tridentctl version --client", expected = "{{version}}" } diff --git a/schema/mise-registry-tool.json b/schema/mise-registry-tool.json index f6948403fc..cdb777aada 100644 --- a/schema/mise-registry-tool.json +++ b/schema/mise-registry-tool.json @@ -74,14 +74,6 @@ "description": "List of backends that can install this tool", "minItems": 1 }, - "depends": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[a-zA-Z0-9_.-]+$" - }, - "description": "Other tools this tool depends on" - }, "description": { "type": "string", "description": "A brief description of the tool" @@ -126,6 +118,14 @@ "expected": { "type": "string", "description": "Expected substring in the command output" + }, + "tools": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-zA-Z0-9_.-]+$" + }, + "description": "Additional mise tools to install before running test.cmd. Used only by mise test-tool." } }, "required": ["cmd", "expected"], diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 77a73a0ff7..52c890fabc 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -714,10 +714,6 @@ pub trait Backend: Debug + Send + Sync { deps.extend(self.get_optional_dependencies()?); } let mut deps: IndexSet<_> = deps.into_iter().map(BackendArg::from).collect(); - if let Some(rt) = REGISTRY.get(self.ba().short.as_str()) { - // add dependencies from registry/ - deps.extend(rt.depends.iter().map(BackendArg::from)); - } deps.retain(|ba| &**self.ba() != ba); deps.retain(|ba| !all_fulls.contains(&ba.full())); for ba in deps.clone() { diff --git a/src/cli/test_tool.rs b/src/cli/test_tool.rs index 797190d087..6d3b79bfda 100644 --- a/src/cli/test_tool.rs +++ b/src/cli/test_tool.rs @@ -60,10 +60,18 @@ impl TestTool { { continue; } - let (cmd, expected) = if let Some(test) = &rt.test { - (test.0.to_string(), test.1.to_string()) + let (cmd, expected, tools) = if let Some(test) = rt.test.as_ref() { + ( + test.cmd.to_string(), + test.expected.to_string(), + test.tools.iter().map(|tool| tool.to_string()).collect(), + ) } else if self.include_non_defined { - (format!("{} --version", tool.short), "__TODO__".to_string()) + ( + format!("{} --version", tool.short), + "__TODO__".to_string(), + vec![], + ) } else { continue; }; @@ -72,6 +80,7 @@ impl TestTool { tool, cmd, expected, + tools, }); } @@ -135,7 +144,13 @@ impl TestTool { let tool = target.tool.short.clone(); let start = std::time::Instant::now(); let result = match self - .test(&config, &target.tool, &target.cmd, &target.expected) + .test( + &config, + &target.tool, + &target.cmd, + &target.expected, + &target.tools, + ) .await { Ok(output) => TestToolResult { @@ -337,6 +352,7 @@ impl TestTool { tool: &ToolArg, cmd: &str, expected: &str, + test_tools: &[String], ) -> Result { let mut config = config.clone(); let mut args = vec![tool.clone()]; @@ -348,6 +364,12 @@ impl TestTool { .map(|ba| ba.to_string().parse()) .collect::>>()?, ); + args.extend( + test_tools + .iter() + .map(|tool| tool.parse()) + .collect::>>()?, + ); let mut ts = ToolsetBuilder::new() .with_args(&args) .with_default_to_latest(true) @@ -444,6 +466,7 @@ struct TestToolTarget { tool: ToolArg, cmd: String, expected: String, + tools: Vec, } struct TestToolResult { diff --git a/src/registry.rs b/src/registry.rs index 333975897f..87db10036a 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -25,13 +25,19 @@ pub struct RegistryTool { #[allow(unused)] pub aliases: &'static [&'static str], pub overrides: &'static [&'static str], - pub test: &'static Option<(&'static str, &'static str)>, + pub test: &'static Option, pub os: &'static [&'static str], - pub depends: &'static [&'static str], pub idiomatic_files: &'static [&'static str], pub detect: &'static [&'static str], } +#[derive(Debug, Clone)] +pub struct RegistryToolTest { + pub cmd: &'static str, + pub expected: &'static str, + pub tools: &'static [&'static str], +} + #[derive(Debug, Clone)] pub struct RegistryBackend { pub full: &'static str,