Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions e2e/lockfile/test_lockfile_v_prefix
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash

# Test that lockfile matching works when mise.toml uses "v" prefix but lockfile doesn't

export MISE_LOCKFILE=1

detect_platform
PLATFORM="$MISE_PLATFORM"

# --- Test: "v" prefix in mise.toml matches lockfile without "v" prefix ---
cat <<'EOF' >mise.toml
[tools]
jq = "v1.7.1"
EOF

cat <<EOF >mise.lock
[[tools.jq]]
version = "1.7.1"
backend = "aqua:jqlang/jq"
"platforms.$PLATFORM" = { url = "https://example.com/jq-1.7.1.tar.gz" }
EOF

# --locked --dry-run should succeed (version should match despite "v" prefix)
assert_contains "mise install --locked --dry-run 2>&1" "would install"
8 changes: 7 additions & 1 deletion src/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,13 @@ pub fn get_locked_version(
let mut matching: Vec<_> = tools
.iter()
.filter(|v| {
let version_matches = prefix == "latest" || v.version.starts_with(prefix);
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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
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);

let options_match = &v.options == request_options;
version_matches && options_match
})
Expand Down
Loading