Skip to content

Commit

Permalink
Fix handling of sys.base_prefix collision in interpreter identity c…
Browse files Browse the repository at this point in the history
…heck during tool installs (#7596)

Closes #7586

Extends #7593 (thanks @lucab!)

---------

Co-authored-by: Luca BRUNO <lucab@lucabruno.net>
  • Loading branch information
zanieb and lucab authored Sep 20, 2024
1 parent e93b54e commit d6c9603
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/uv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ owo-colors = { workspace = true }
rayon = { workspace = true }
regex = { workspace = true }
rustc-hash = { workspace = true }
same-file = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tempfile = { workspace = true }
Expand Down
24 changes: 17 additions & 7 deletions crates/uv/src/commands/tool/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,23 @@ pub(crate) async fn install(
installed_tools
.get_environment(&from.name, &cache)?
.filter(|environment| {
// NOTE(lucab): this compares `base_prefix` paths as a proxy for
// detecting interpreters mismatches. Directly comparing interpreters
// (by paths or binaries on-disk) would result in several false
// positives on Windows due to file-copying and shims.
let old_base_prefix = environment.interpreter().sys_base_prefix();
let selected_base_prefix = interpreter.sys_base_prefix();
if old_base_prefix == selected_base_prefix {
// TODO(zanieb): Consider using `sysconfig.get_path("stdlib")` instead, which
// should be generally robust.
// TODO(zanieb): Move this into a utility on `Interpreter` since it's non-trivial.
let same_interpreter = if cfg!(windows) {
// On Windows, we can't canonicalize an interpreter based on its executable path
// because the executables are separate shim files (not links). Instead, we
// compare the `sys.base_prefix`.
let old_base_prefix = environment.interpreter().sys_base_prefix();
let selected_base_prefix = interpreter.sys_base_prefix();
old_base_prefix == selected_base_prefix
} else {
// On Unix, we can see if the canonicalized executable is the same file.
environment.interpreter().sys_executable() == interpreter.sys_executable()
|| same_file::is_same_file(environment.interpreter().sys_executable(), interpreter.sys_executable()).unwrap_or(false)
};

if same_interpreter {
trace!(
"Existing interpreter matches the requested interpreter for `{}`: {}",
from.name,
Expand Down

0 comments on commit d6c9603

Please sign in to comment.