Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
63 changes: 63 additions & 0 deletions e2e/cli/test_exec_lockfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash

# `mise x` should only touch the project lockfile when the install resolves
# the same version specifier as the config. CLI overrides
# (`mise x tool@<version>`) carry a different specifier, so pairing the
# config's request with their installed version would produce a nonsensical
# lockfile entry.

export MISE_LOCKFILE=1

cat <<EOF >mise.toml
[tools]
dummy = "1"
EOF

mise uninstall dummy --all
mise install dummy@1.0.0
touch mise.lock
mise lock --platform linux-x64
assert_contains "cat mise.lock" "1.0.0"

# `mise x dummy@2.0.0` resolves to 2.0.0 — an explicit CLI override that
# doesn't satisfy `dummy = "1"`. Lockfile must stay at 1.0.0.
mise x dummy@2.0.0 -- dummy
assert_contains "cat mise.lock" "1.0.0"
assert_not_contains "cat mise.lock" "2.0.0"

# Same for `mise x dummy@latest` — the latest is 2.0.0, and the lockfile
# must not adopt it under the `"1"` request.
mise x dummy@latest -- dummy
assert_contains "cat mise.lock" "1.0.0"
assert_not_contains "cat mise.lock" "2.0.0"

# `mise x dummy` (no version) carries the config's `"1"` specifier, so it
# isn't an override. Verify it still resolves and runs against the locked
# 1.0.0 (and would be allowed to populate the lockfile entry — exercised by
# the empty-lockfile case below).
mise x dummy -- dummy
assert_contains "cat mise.lock" "1.0.0"

# Env-var overrides (`MISE_<TOOL>_VERSION=...`) are the same class of
# override as CLI args — they carry a `ToolSource::Environment` and a
# version specifier that may not match the config's. The version-match
# check covers them too: with mise.toml `dummy = "1"`, setting
# `MISE_DUMMY_VERSION=2` must not pair the "1" request with a 2.x install.
MISE_DUMMY_VERSION=2 mise install
assert_contains "cat mise.lock" "1.0.0"
assert_not_contains "cat mise.lock" "2.0.0"

# `mise upgrade` is the supported way to explicitly bump the lockfile and
# *should* update it (it remaps Argument → MiseToml before update_lockfiles).
mise upgrade dummy@1.1.0
assert_contains "cat mise.lock" "1.1.0"
assert_not_contains "cat mise.lock" "1.0.0"

# `mise x dummy` against an empty (but existing) lockfile must populate the
# entry — the install satisfies the config's `"1"` request, so propagation
# is correct.
mise uninstall dummy --all
echo "" >mise.lock
mise x dummy -- dummy
assert_contains "cat mise.lock" "dummy"
assert_contains "cat mise.lock" "1.1.0"
6 changes: 1 addition & 5 deletions mise.lock
Original file line number Diff line number Diff line change
Expand Up @@ -583,13 +583,9 @@ checksum = "sha256:795670a80d35b23e7ecf932ede742609f2267314f2df64054b020698fcc8a
url = "https://github.com/LuaLS/lua-language-server/releases/download/3.17.1/lua-language-server-3.17.1-win32-x64.zip"

[[tools.node]]
version = "25.9.0"
version = "24.15.0"
backend = "core:node"

[tools.node."platforms.linux-x64"]
checksum = "sha256:134e55b2408448a219760fe04dc44d6851f9de8a79549021ffd870e9082d9e7b"
url = "https://nodejs.org/dist/v25.9.0/node-v25.9.0-linux-x64.tar.gz"

[[tools."npm:ajv-cli"]]
version = "5.0.0"
backend = "npm:ajv-cli"
Expand Down
19 changes: 19 additions & 0 deletions src/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,25 @@ pub fn update_lockfiles(config: &Config, ts: &Toolset, new_versions: &[ToolVersi
.ok()
.map(|(idx, tv)| (idx, tv.request.clone()))
{
// Only propagate when the new install resolves the same
// version specifier as the config. `mise x node` (no
// version) is rewritten by `with_default_to_latest` to
// carry the config's version string, so it matches and
// updates the lockfile as expected. `mise x node@latest`
// with mise.toml `node = "24"` carries a "latest"
// specifier that doesn't match — that's an ad-hoc CLI
// override and pairing the "24" request with a 25.x
// install would produce a nonsensical lockfile entry.
if new_version.request.version() != request.version() {
trace!(
"skipping lockfile update for {}@{} in {}: CLI override does not match config request {}",
new_version.short(),
new_version.version,
display_path(&lockfile_path),
request.version(),
);
continue;
}
let mut new_version = new_version.clone();
new_version.request = request;
versions.remove(idx);
Expand Down
Loading