-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
fix(link): linked versions override lockfile during resolution #8050
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,41 @@ | ||||||||
| #!/usr/bin/env bash | ||||||||
|
|
||||||||
| # Test that linked tools are not reported as missing when a lockfile exists | ||||||||
| # Regression test for https://github.com/jdx/mise/discussions/8049 | ||||||||
|
|
||||||||
| export MISE_LOCKFILE=1 | ||||||||
|
|
||||||||
| echo "=== Setup: install tiny and create a linked version ===" | ||||||||
| rm -f mise.toml mise.lock | ||||||||
| mise install tiny@3.1.0 | ||||||||
|
|
||||||||
| # Create a directory to link as a fake "brew" version | ||||||||
| mkdir -p "$PWD/tmp/tiny-brew" | ||||||||
|
|
||||||||
| # Link it as tiny@brew (absolute symlink, like `mise link hk@brew $(brew --prefix hk)`) | ||||||||
| mise link tiny@brew "$PWD/tmp/tiny-brew" | ||||||||
| assert_contains "mise ls tiny" "brew (symlink)" | ||||||||
|
|
||||||||
| echo "=== Create mise.toml requesting latest and a lockfile pinning 3.1.0 ===" | ||||||||
| cat <<EOF >mise.toml | ||||||||
| [tools] | ||||||||
| tiny = "latest" | ||||||||
| EOF | ||||||||
|
|
||||||||
| # Create a lockfile that pins tiny to 3.1.0 | ||||||||
| cat <<EOF >mise.lock | ||||||||
| [tools.tiny] | ||||||||
| version = "3.1.0" | ||||||||
| EOF | ||||||||
|
|
||||||||
| echo "=== Verify linked version is used instead of lockfile version ===" | ||||||||
| # The linked version should take priority over the lockfile entry | ||||||||
| # Previously this would show tiny@3.1.0 as (missing) alongside the linked version | ||||||||
| assert_contains "mise ls tiny" "brew (symlink)" | ||||||||
| assert_not_contains "mise ls tiny" "missing" | ||||||||
|
|
||||||||
| echo "=== Cleanup ===" | ||||||||
| rm -rf mise.toml mise.lock tmp/tiny-brew | ||||||||
| mise uninstall tiny@brew 2>/dev/null || true | ||||||||
|
||||||||
| mise uninstall tiny@brew 2>/dev/null || true | |
| mise uninstall tiny@brew 2>/dev/null || true | |
| mise uninstall tiny@3.1.0 2>/dev/null || true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,6 +50,7 @@ impl ToolVersion { | |
| ) -> Result<Self> { | ||
| trace!("resolving {} {}", &request, opts); | ||
| if opts.use_locked_version | ||
| && !has_linked_version(request.ba()) | ||
| && let Some(lt) = request.lockfile_resolve(config)? | ||
| { | ||
|
Comment on lines
52
to
55
|
||
| let mut tv = Self::new(request.clone(), lt.version); | ||
|
|
@@ -412,6 +413,27 @@ impl Default for ResolveOptions { | |
| } | ||
| } | ||
|
|
||
| /// Check if a tool has any user-linked versions (created by `mise link`). | ||
| /// A linked version is an installed version whose path is a symlink to an absolute path, | ||
| /// as opposed to runtime symlinks which point to relative paths (starting with "./"). | ||
| fn has_linked_version(ba: &BackendArg) -> bool { | ||
| let installs_dir = &ba.installs_path; | ||
| let Ok(entries) = std::fs::read_dir(installs_dir) else { | ||
| return false; | ||
| }; | ||
| for entry in entries.flatten() { | ||
| let path = entry.path(); | ||
| if let Ok(Some(target)) = crate::file::resolve_symlink(&path) { | ||
| // Runtime symlinks start with "./" (e.g., latest -> ./1.35.0) | ||
| // User-linked symlinks point to absolute paths (e.g., brew -> /opt/homebrew/opt/hk) | ||
| if target.is_absolute() { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| false | ||
|
Comment on lines
+424
to
+434
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This entries.flatten().any(|entry| {
if let Ok(Some(target)) = crate::file::resolve_symlink(&entry.path()) {
target.is_absolute()
} else {
false
}
}) |
||
| } | ||
|
Comment on lines
+419
to
+435
|
||
|
|
||
| impl Display for ResolveOptions { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { | ||
| let mut opts = vec![]; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test installs
tiny@3.1.0but does not uninstall it during cleanup. If the e2e suite shares a persistent MISE data directory across tests, that leftover install can cause cross-test state leakage. Consider uninstallingtiny@3.1.0in cleanup as well (or run the test under an isolated temp data dir if that鈥檚 the suite convention).