fix(install): normalize "v" prefix when matching lockfile versions#8413
fix(install): normalize "v" prefix when matching lockfile versions#8413
Conversation
When mise.toml specifies a version with a "v" prefix (e.g., "v0.23.1") but the lockfile stores the resolved version without it (e.g., "0.23.1"), --locked mode would fail with "is not in the lockfile". Strip the "v"/"V" prefix before comparing so both forms match. Fixes #8411 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the robustness of Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request addresses an issue where versions with a 'v' prefix in mise.toml failed to match versions without it in the lockfile. The fix involves normalizing the version prefix before comparison, which is a good approach. The new end-to-end test effectively validates this scenario. I've identified a potential bug in a corner case of the implementation and suggested a more robust solution to ensure all prefix combinations are handled correctly.
src/lockfile.rs
Outdated
| let norm_prefix = prefix | ||
| .strip_prefix('v') | ||
| .or(prefix.strip_prefix('V')) | ||
| .unwrap_or(prefix); | ||
| let version_matches = prefix == "latest" | ||
| || v.version.starts_with(prefix) | ||
| || v.version.starts_with(norm_prefix); |
There was a problem hiding this comment.
The current logic for matching versions is a good improvement. However, it has a potential bug where it fails to match if the lockfile version has a v prefix but the requested version (prefix) does not (e.g., prefix is "1.0.0" and v.version is "v1.0.0").
A more robust approach is to normalize both the prefix and v.version by stripping any 'v'/'V' prefix before comparison. This ensures that all combinations of prefixes are handled correctly and simplifies the matching logic.
| let norm_prefix = prefix | |
| .strip_prefix('v') | |
| .or(prefix.strip_prefix('V')) | |
| .unwrap_or(prefix); | |
| let version_matches = prefix == "latest" | |
| || v.version.starts_with(prefix) | |
| || v.version.starts_with(norm_prefix); | |
| let norm_prefix = prefix | |
| .strip_prefix('v') | |
| .or(prefix.strip_prefix('V')) | |
| .unwrap_or(prefix); | |
| let norm_v_version = v.version.strip_prefix('v') | |
| .or(v.version.strip_prefix('V')) | |
| .unwrap_or(&v.version); | |
| let version_matches = prefix == "latest" || norm_v_version.starts_with(norm_prefix); |
Also strip "v"/"V" prefix from the lockfile version, not just the requested prefix. This handles the reverse case where the lockfile has a "v" prefix but the request does not. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR fixes a bug where Changes:
The implementation correctly handles the reported issue and maintains backward compatibility with existing version matching logic. Confidence Score: 5/5
Important Files Changed
Last reviewed commit: cbaaa8e |
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 x -- echo |
29.2 ± 0.7 | 27.8 | 35.2 | 1.18 ± 0.05 |
mise x -- echo |
24.8 ± 0.9 | 23.5 | 33.0 | 1.00 |
✅ Performance improvement for x -- echo is 18% |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 env |
29.4 ± 1.2 | 27.2 | 38.2 | 1.22 ± 0.06 |
mise env |
24.2 ± 0.7 | 22.9 | 27.0 | 1.00 |
✅ Performance improvement for env is 22% |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 hook-env |
30.6 ± 1.2 | 28.6 | 37.3 | 1.20 ± 0.06 |
mise hook-env |
25.4 ± 0.9 | 23.8 | 30.6 | 1.00 |
✅ Performance improvement for hook-env is 20% |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 ls |
24.1 ± 0.8 | 22.6 | 29.1 | 1.04 ± 0.05 |
mise ls |
23.1 ± 1.0 | 21.5 | 28.8 | 1.00 |
xtasks/test/perf
| Command | mise-2026.2.24 | mise | Variance |
|---|---|---|---|
| install (cached) | 169ms | 156ms | +8% |
| ls (cached) | 92ms | 84ms | +9% |
| bin-paths (cached) | 100ms | ✅ 89ms | +12% |
| task-ls (cached) | 889ms | 857ms | +3% |
✅ Performance improvement: bin-paths cached is 12%
### 🚀 Features - **(hooks)** add task references to hooks and watch_files by @jdx in [#8400](#8400) - **(prepare)** add git-submodule built-in provider by @jdx in [#8407](#8407) - **(prepare)** add human-readable stale reasons to prepare output by @jdx in [#8408](#8408) - **(prepare)** add dependency ordering to prepare steps by @jdx in [#8401](#8401) - **(prepare)** add --explain flag for provider diagnostics by @jdx in [#8409](#8409) - **(prepare)** add per-provider timeout support by @jdx in [#8405](#8405) - **(prepare)** add blake3 content-hash freshness checking by @jdx in [#8404](#8404) - **(tasks)** monorepo vars and per-task vars by @halms in [#8248](#8248) ### 🐛 Bug Fixes - **(aqua)** restore bin_paths disk cache with fresh_file invalidation by @jdx in [#8398](#8398) - **(idiomatic)** use generic parser for idiomatic files by @risu729 in [#8171](#8171) - **(install)** apply precompiled options to all platforms in lockfile by @jdx in [#8396](#8396) - **(install)** normalize "v" prefix when matching lockfile versions by @jdx in [#8413](#8413) - **(prepare)** improve git submodule parser and fix check_staleness error handling by @jdx in [#8412](#8412) - **(python)** respect precompiled settings in lock file generation by @jdx in [#8399](#8399) - **(python)** clarify uv_venv_auto docs + prevent uv shim recursion in venv creation by @halms in [#8402](#8402) - **(task)** remove deprecated `# mise` task header syntax by @jdx in [#8403](#8403) - **(vfox)** avoid eager metadata loading during config file detection by @jdx in [#8397](#8397) - clarify GitHub attestations to be artifact ones by @scop in [#8394](#8394) - ignore comments in idiomatic version files by @iloveitaly in [#7682](#7682) ### 🚜 Refactor - unify archive detection by @risu729 in [#8137](#8137) ### 📚 Documentation - remove duplicated docs for npm.package_manager by @risu729 in [#8414](#8414)
Summary
mise.tomlspecifies a version with a "v" prefix (e.g.,setup-envtest = "v0.23.1") but the lockfile stores the resolved version without it (version = "0.23.1"),--lockedmode would fail with "is not in the lockfile"Fixes #8411
Test plan
test_lockfile_v_prefixthat verifies--locked --dry-runsucceeds when mise.toml has "v" prefix and lockfile doesn'ttest_lockfile_locked_mode,test_lockfile_install) still pass🤖 Generated with Claude Code
Note
Low Risk
Low risk: small, localized change to lockfile version matching that only relaxes comparisons by ignoring a leading
v/V, plus an e2e test to cover the regression.Overview
get_locked_versionnow normalizes tool version prefixes by stripping a leadingv/Vfrom both the requested version and lockfile entries before doing thestarts_withmatch, preventing--lockedfailures whenmise.tomlusesv1.2.3butmise.lockstores1.2.3.Adds an e2e regression test (
test_lockfile_v_prefix) that writes amise.tomlwithjq = "v1.7.1"and a lockfile withversion = "1.7.1", assertingmise install --locked --dry-runsucceeds.Written by Cursor Bugbot for commit cbaaa8e. This will update automatically on new commits. Configure here.