fix(auto-install): support installing non-active backend versions#6484
fix(auto-install): support installing non-active backend versions#6484
Conversation
Fixes auto-install when a tool has different versions globally and locally. Previously, if a user had node@24 globally and node@20 locally (not installed), the auto-install feature would not work because it only checked currently active installed versions. Now checks all requested backends and looks for any installed version that provides the binary, then installs missing versions for those backends. Also removes the user_attended() check from shims to make auto-install behavior consistent with `mise x` and `mise run`. Fixes #6482 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull Request Overview
This PR fixes the auto-install feature when a tool has different versions globally and locally, where the local version is not installed. Previously, auto-install only checked currently active installed versions, causing it to fail when the required local version wasn't installed.
- Enhanced the
install_missing_binfunction to check all requested backends for any installed versions that provide the binary - Removed the
user_attended()check from shims to make auto-install behavior consistent - Added comprehensive e2e tests covering both hook-not-found and shim auto-install scenarios
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/toolset/mod.rs | Enhanced install_missing_bin to check all requested backends for installed versions that provide the binary |
| src/shims.rs | Removed user_attended() check to enable consistent auto-install behavior |
| e2e/cli/test_hook_not_found_auto_install | New comprehensive test covering both auto-install paths |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| // This handles the case where a user has tool@v1 globally and tool@v2 locally (not installed) | ||
| // When looking for a bin provided by the tool, we check if any installed version provides it | ||
| let all_installed = self.list_installed_versions(config).await?; | ||
| for (backend, _versions) in self.list_versions_by_plugin() { |
There was a problem hiding this comment.
The list_installed_versions call is made for every iteration of the loop, but it's called outside the loop. However, the loop iterates over all backends and calls list_versions_by_plugin() which could be expensive. Consider caching the result or restructuring to avoid redundant lookups if this method is called frequently.
| for (backend, _versions) in self.list_versions_by_plugin() { | |
| let all_versions_by_plugin = self.list_versions_by_plugin(); | |
| for (backend, _versions) in all_versions_by_plugin { |
src/toolset/mod.rs
Outdated
| } | ||
|
|
||
| // Check if this backend has ANY installed version in the system | ||
| if let Some((_, tv)) = all_installed.iter().find(|(p, _)| p.ba() == backend.ba()) { |
There was a problem hiding this comment.
The linear search through all_installed for each backend could be inefficient with many installed tools. Consider using a HashMap or BTreeMap indexed by backend identifier for O(1) lookups instead of O(n) search.
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.9.24 x -- echo |
20.8 ± 0.4 | 19.8 | 23.0 | 1.00 |
mise x -- echo |
21.3 ± 0.5 | 20.1 | 22.8 | 1.02 ± 0.03 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.9.24 env |
20.3 ± 0.5 | 19.4 | 25.8 | 1.00 |
mise env |
20.7 ± 0.6 | 19.5 | 24.0 | 1.02 ± 0.04 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.9.24 hook-env |
20.0 ± 0.8 | 19.1 | 32.8 | 1.00 |
mise hook-env |
20.3 ± 0.4 | 19.4 | 21.9 | 1.02 ± 0.04 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.9.24 ls |
17.6 ± 0.4 | 16.8 | 18.7 | 1.00 |
mise ls |
18.2 ± 1.0 | 17.1 | 35.4 | 1.03 ± 0.06 |
xtasks/test/perf
| Command | mise-2025.9.24 | mise | Variance |
|---|---|---|---|
| install (cached) | 171ms | ✅ 107ms | +59% |
| ls (cached) | 65ms | 66ms | -1% |
| bin-paths (cached) | 71ms | 72ms | -1% |
| task-ls (cached) | 487ms | 486ms | +0% |
✅ Performance improvement: install cached is 59%
The install_missing_bin function was using find() to check if a backend provides a binary, which only checked the first installed version found. This incorrectly excluded backends from auto-install if their first installed version didn't provide the binary, even when other installed versions did. Changed to iterate through all installed versions of each backend to properly detect if any version provides the requested binary. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
### 🐛 Bug Fixes - **(auto-install)** support installing non-active backend versions by @jdx in [#6484](#6484) - **(task)** prevent hang when tasks with multiple dependencies fail by @stempler in [#6481](#6481) ### 🧪 Testing - **(e2e)** use local HTTP server instead of httpbin.org for tool-stub tests by @jdx in [#6488](#6488) ### New Contributors - @stempler made their first contribution in [#6481](#6481) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Bumps to 2025.9.25 with changelog updates (bug fixes, testing), adds `mdsf` to the aqua registry, and updates completions and packaging metadata. > > - **Release v2025.9.25** > - Update versions in `Cargo.toml`, `Cargo.lock`, `default.nix`, `packaging/rpm/mise.spec`, and `README.md`. > - Refresh shell completion cache spec filenames in `completions/_mise`, `completions/mise.bash`, and `completions/mise.fish`. > - Expand `CHANGELOG.md` with 2025.9.25 entry (bug fixes and testing notes). > - **Registry** > - Add `hougesen/mdsf` package: `crates/aqua-registry/aqua-registry/pkgs/hougesen/mdsf/registry.yaml`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6debaab. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: mise-en-dev <release@mise.jdx.dev>
Summary
Fixes auto-install when a tool has different versions globally and locally (not installed).
Problem
Previously, if a user had
node@24globally andnode@20locally (not installed), the auto-install feature would not work because it only checked currently active installed versions.Example scenario:
node@24installed globallynode@20(not installed)nodecommandnode@20Solution
Modified
install_missing_binto check all requested backends and look for any installed version that provides the binary, then install missing versions for those backends.Also removed the
user_attended()check from shims to make auto-install behavior consistent withmise xandmise run.Test plan
Changes
src/toolset/mod.rs: Enhancedinstall_missing_binto check all requested backendssrc/shims.rs: Removeduser_attended()check from shim auto-installe2e/cli/test_hook_not_found_auto_install: New test for both auto-install pathsFixes #6482 (comment)
🤖 Generated with Claude Code
Note
Enables auto-install for tools required by the project even when only other versions are installed, makes shim-triggered auto-install unconditional, and adds e2e coverage.
src/toolset/mod.rs: Expandinstall_missing_binto consider requested backends that have any installed version providing the bin, then install missing versions for those backends.src/shims.rs: Removeconsole::user_attended()check sonot_found_auto_installruns from shims.e2e/cli/test_hook_not_found_auto_installcovering hook-not-found and shim-based auto-install (tiny 3.0.0 vs 3.1.0).Written by Cursor Bugbot for commit 0910ba1. This will update automatically on new commits. Configure here.