diff --git a/e2e/cli/test_reshim_with_shims_on_path b/e2e/cli/test_reshim_with_shims_on_path new file mode 100755 index 0000000000..3dfa7b1bb0 --- /dev/null +++ b/e2e/cli/test_reshim_with_shims_on_path @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Regression test: when shims are on PATH and a "mise" shim exists (e.g. because +# core:rust is managed and ~/.cargo/bin contains the mise binary), +# `mise reshim` should still create shims pointing to the real mise binary, +# not to the mise shim itself (which would create a circular symlink). +# Similarly, `mise doctor` should not report shims as missing. + +shimdir="$MISE_DATA_DIR/shims" +mise_bin="$(which mise)" + +# Install a tool so there are shims to create +mise i dummy@latest + +# Reshim without shims on PATH — baseline +mise reshim + +# Verify shim was created and points to the real binary +assert "readlink $shimdir/dummy" "$mise_bin" + +# Simulate what happens when core:rust is in the toolset: the mise binary +# itself ends up with a shim because ~/.cargo/bin (containing mise) is scanned +# as a tool bin directory. Create a mise shim pointing to the real binary. +ln -sf "$mise_bin" "$shimdir/mise" + +# Now put shims on PATH (as mise activate --shims does in non-interactive shells) +export PATH="$shimdir:$PATH" + +# Reshim WITH shims on PATH and a mise shim present. +# Previously this caused file::which("mise") to find the shim, leading to +# circular symlinks (shim pointing to itself) and broken doctor output. +mise reshim + +# Shim should still point to the real mise binary, not to the shim directory +assert "readlink $shimdir/dummy" "$mise_bin" +assert_not_contains "readlink $shimdir/dummy" "$shimdir" + +# The mise shim itself must not be circular +if [ -L "$shimdir/mise" ]; then + assert_not_contains "readlink $shimdir/mise" "$shimdir" +fi + +# Doctor should not report missing shims +assert_not_contains "mise doctor" "shims are missing" diff --git a/src/cli/doctor/mod.rs b/src/cli/doctor/mod.rs index 930be24d1e..26616bd131 100644 --- a/src/cli/doctor/mod.rs +++ b/src/cli/doctor/mod.rs @@ -385,7 +385,7 @@ impl Doctor { } async fn analyze_shims(&mut self, config: &Arc, toolset: &Toolset) { - let mise_bin = file::which("mise").unwrap_or(env::MISE_BIN.clone()); + let mise_bin = file::which_no_shims("mise").unwrap_or(env::MISE_BIN.clone()); if let Ok((missing, extra)) = shims::get_shim_diffs(config, mise_bin, toolset).await { let cmd = style::nyellow("mise reshim"); diff --git a/src/shims.rs b/src/shims.rs index 70f310185f..1648d108be 100644 --- a/src/shims.rs +++ b/src/shims.rs @@ -124,7 +124,7 @@ pub async fn reshim(config: &Arc, ts: &Toolset, force: bool) -> Result<( }) .lock(); - let mise_bin = file::which("mise").unwrap_or(env::MISE_BIN.clone()); + let mise_bin = file::which_no_shims("mise").unwrap_or(env::MISE_BIN.clone()); let mise_bin = mise_bin.absolutize()?; // relative paths don't work as shims #[cfg(windows)]