Skip to content

fix(lockfile): respect locked versions for prefix: tool requests - #11255

Merged
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-lockfile-prefix-requests
Jul 24, 2026
Merged

jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-lockfile-prefix-requests

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • match prefix: tool requests against the lockfile using the bare prefix, so mise install honors the locked version instead of re-resolving to the newest match
  • also strip the prefix: scheme in the post-alias lockfile re-check, so aliases that resolve to prefix selectors are pinned too
  • add a unit test for the new query mapping and an e2e test covering pin / no-op reinstall / upgrade-bump / stale-entry / alias-to-prefix

Context

Fixes the unresolved behavior reported in #5781: with uv = 'prefix:0.8' and lockfile = true, mise install installed the newest prefix match and rewrote .mise.lock, so the lockfile had zero pinning effect — install behaved like an implicit upgrade. jdx noted at the time that lockfile "isn't compatible with prefix: yet"; this makes it compatible.

Root cause: the resolution-time lockfile short-circuit calls ToolRequest::lockfile_resolve, which matches the request string against stored versions via starts_with. For Prefix requests, version() returns the scheme-qualified form (prefix:0.8), which can never starts-with-match a stored concrete version like 0.8.1. The short-circuit therefore never fired and resolve_prefix picked the newest match (install runs with latest_versions: true).

Fix: lockfile_resolve now derives its match string from a new lockfile_version_query() helper — the bare prefix for Prefix requests, version() for everything else (ref:/path:/system entries store that string verbatim; sub- gets its lockfile check after subtraction in resolve_version). This makes prefix:0.8 behave exactly like the fuzzy version request "0.8" already does. The same one-line strip is applied in the post-alias re-check (the #8194 path), covering [tool_alias.X.versions] my1 = "prefix:1".

Semantics preserved:

  • mise upgrade / mise lock --bump / mise x tool@... / tool stubs all run with use_locked_version: false and still bypass the lock — constrained upgrades (prefix:0.8 bumping within 0.8.x) keep working, which is exactly the reporter's desired workflow.
  • A lock entry that no longer satisfies the prefix (config changed) is ignored and resolution falls through to a fresh pick.
  • Lockfile matching stays the existing plain starts_with (same semantics fuzzy Version requests have today); noted in the helper's doc comment.

Out of scope, noted for completeness: sub- requests (relative-to-latest by design), and the --locked strict-mode "not in lockfile" bail which today only exists in the Version arm.

Reproduced pre-fix on v2026.7.x (isolated env): jq = 'prefix:1.7' with .mise.lock seeded to 1.7 → mise install installed 1.7.1 and rewrote the lock. Post-fix (debug build): install keeps 1.7.

Tests

  • cargo fmt --check
  • new unit test test_lockfile_version_query_uses_bare_prefix
  • new e2e/lockfile/test_lockfile_prefix (dummy plugin, no network): locked older version survives mise install (fails before this fix), reinstall is a no-op, mise upgrade still bumps within the prefix and updates the lock, a non-matching lock entry falls through to fresh resolution, and an alias resolving to prefix:1 is pinned the same way

This PR was prepared by an AI coding assistant.

Summary by CodeRabbit

  • Bug Fixes

    • Improved lockfile resolution for prefix: selectors so pinned versions are preserved correctly, including after alias resolution.
    • Added boundary-aware prefix matching to prevent stale cross-boundary matches (e.g., prefix:1 won’t match 10.0.0, and empty prefixes are rejected).
    • Updated locked-version lookup to use normalized, boundary-enforced prefix queries when appropriate.
  • Tests

    • Added an end-to-end lockfile test covering pin preservation, idempotency, upgrade behavior, and stale/out-of-range scenarios.
    • Added unit test coverage for the new boundary prefix matching logic.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 5d0f3008-54b9-47c4-bc25-3d2d5578c524

📥 Commits

Reviewing files that changed from the base of the PR and between 9f38d92 and f2ce24e.

📒 Files selected for processing (4)
  • e2e/lockfile/test_lockfile_prefix
  • src/lockfile.rs
  • src/toolset/tool_request.rs
  • src/toolset/tool_version.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/toolset/tool_version.rs
  • src/lockfile.rs
  • src/toolset/tool_request.rs
  • e2e/lockfile/test_lockfile_prefix

📝 Walkthrough

Walkthrough

Prefix selectors now use bare values and boundary-aware matching when resolving lockfile entries, including selectors obtained through aliases. Unit and end-to-end tests cover lock reuse, upgrades, non-matching versions, boundary cases, and alias-based resolution.

Changes

Prefix lockfile resolution

Layer / File(s) Summary
Normalize prefix lockfile queries
src/toolset/tool_request.rs, src/toolset/tool_version.rs
Direct and alias-resolved prefix selectors strip the prefix: scheme and propagate boundary enforcement to lockfile lookups; unit coverage verifies query behavior.
Enforce prefix version boundaries
src/lockfile.rs
Lockfile matching rejects empty prefixes and textual matches that cross version-separator boundaries, such as 1 matching 10.0.0.
Validate prefix pinning behavior
e2e/lockfile/test_lockfile_prefix
End-to-end coverage verifies lock reuse, install idempotency, upgrades, replacement of non-matching entries, boundary rejection, and alias resolution.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ToolRequest
  participant ToolVersion
  participant Lockfile
  ToolRequest->>Lockfile: Query bare prefix with boundary enforcement
  ToolVersion->>Lockfile: Query alias-resolved bare prefix
  Lockfile-->>ToolRequest: Return boundary-matching locked version
  Lockfile-->>ToolVersion: Return boundary-matching locked version
Loading

Poem

A rabbit found a lock in the hay,
With boundaries keeping stale hops away.
Aliases joined the tune,
Pins stayed fixed through noon,
While upgrades bounded off to play.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: lockfile handling for prefix-based tool requests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes lockfile pinning for direct and alias-derived prefix: requests.

  • Adds boundary-aware matching so unrelated versions and empty prefixes are rejected.
  • Adds unit and end-to-end coverage for pinning, reinstall, upgrade, stale entries, and aliases.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains in the fixes associated with the previous review threads.

Important Files Changed

Filename Overview
src/lockfile.rs Adds prefix-boundary filtering consistent with normal prefix resolution and rejects empty prefix queries.
src/toolset/tool_request.rs Normalizes direct prefix requests to bare lockfile queries while retaining existing behavior for other request variants.
src/toolset/tool_version.rs Applies the same normalized, boundary-aware lockfile lookup after alias resolution.
e2e/lockfile/test_lockfile_prefix Covers locked prefix installation, idempotency, upgrades, stale entries, boundary rejection, and alias-derived prefixes.

Reviews (4): Last reviewed commit: "fix(lockfile): respect locked versions f..." | Re-trigger Greptile

Comment thread src/toolset/tool_request.rs Resolved
Comment thread src/toolset/tool_request.rs Resolved

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/toolset/tool_request.rs`:
- Around line 344-363: Replace the bare prefix lockfile lookup in
ToolRequest::lockfile_version_query with prefix-aware separator-boundary
matching, preserving the selector kind for direct Prefix requests. Apply the
same matcher in the alias-to-prefix resolution path in
src/toolset/tool_version.rs lines 344-347. Extend
e2e/lockfile/test_lockfile_prefix lines 41-49 with a 10.0.0 lock entry and
assert prefix:1 resolves to 1.1.0 rather than 10.0.0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: ef27c531-a3c5-4cab-8d81-8903f0870b4d

📥 Commits

Reviewing files that changed from the base of the PR and between 6f7d7fe and fc1ff07.

📒 Files selected for processing (3)
  • e2e/lockfile/test_lockfile_prefix
  • src/toolset/tool_request.rs
  • src/toolset/tool_version.rs

Comment thread src/toolset/tool_request.rs Resolved
@JamBalaya56562
JamBalaya56562 force-pushed the fix-lockfile-prefix-requests branch 2 times, most recently from 55da3c1 to 9f38d92 Compare July 24, 2026 21:57
With `uv = "prefix:0.8"` and lockfile enabled, `mise install` ignored
the locked version and installed the newest prefix match, rewriting the
lockfile - the lockfile had no pinning effect at all for `prefix:`
requests, making install behave like an implicit upgrade.

Root cause: the lockfile lookup matches the request string against
stored versions with starts_with, but ToolRequest::version() returns
the scheme-qualified form ("prefix:0.8") for Prefix requests, which can
never match a stored concrete version like "0.8.1".

- lockfile_resolve now matches Prefix requests on the bare prefix (via
  a new lockfile_version_query helper), making `prefix:0.8` behave like
  the fuzzy version request "0.8" already does.
- The post-alias lockfile re-check strips a `prefix:` scheme before
  matching, so an alias that resolves to a prefix selector is pinned
  too.
- `mise upgrade` and `mise lock --bump` still bypass the lock via
  use_locked_version=false, so constrained upgrades keep working.

Out of scope: `sub-` requests (relative-to-latest by design; they
already get a bare-version lockfile check after subtraction), and the
--locked strict-mode bail which only exists in the Version arm.

Fixes jdx#5781

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants