From bec06f62bbed4abfc366d095c4fd9218a50d2e24 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 9 Mar 2026 10:39:27 -0400 Subject: [PATCH] Avoid copying /usr in install test (#18372) Closes https://github.com/astral-sh/uv/issues/18361. --------- Co-authored-by: konsti Co-authored-by: Tomasz Kramkowski --- crates/uv/tests/it/tool_install.rs | 51 ++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/crates/uv/tests/it/tool_install.rs b/crates/uv/tests/it/tool_install.rs index 30bf314f3..13786c528 100644 --- a/crates/uv/tests/it/tool_install.rs +++ b/crates/uv/tests/it/tool_install.rs @@ -4693,27 +4693,13 @@ fn tool_install_removed_python() { .with_filtered_exe_suffix(); let tool_dir = context.temp_dir.child("tools"); let bin_dir = context.temp_dir.child("bin"); - let (_, python_executable) = context.python_versions.first().unwrap(); - let install_root = if cfg!(unix) { - // /bin/python3.12 - python_executable.parent().unwrap().parent().unwrap() - } else { - // /python.exe - python_executable.parent().unwrap() - }; - let temp_python_dir = context.temp_dir.child("temp-python"); - copy_dir_all(install_root, &temp_python_dir).unwrap(); - - let relative_path = python_executable.strip_prefix(install_root).unwrap(); - let temp_python = temp_python_dir.join(relative_path); - - // Install `black` using the temporary Python. + // Install `black` with an explicit Python request. uv_snapshot!(context.filters(), context.tool_install() .arg("black") .arg("--python") - .arg(&temp_python) + .arg(python_executable) .env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str()) .env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()) .env(EnvVars::PATH, bin_dir.as_os_str()), @" @@ -4734,7 +4720,38 @@ fn tool_install_removed_python() { Installed 2 executables: black, blackd "); - fs_err::remove_dir_all(&temp_python_dir).unwrap(); + let tool_root = tool_dir.child("black"); + + // Simulate the tool's interpreter disappearing without copying an arbitrary system prefix + // like `/usr` into the test directory. + #[cfg(unix)] + { + let tool_python = tool_root.child("bin").child("python"); + fs_err::remove_file(&tool_python).unwrap(); + fs_err::os::unix::fs::symlink(context.temp_dir.join("missing-python"), &tool_python) + .unwrap(); + } + + #[cfg(windows)] + { + use uv_fs::Simplified; + + let pyvenv_cfg = tool_root.child("pyvenv.cfg"); + let broken_home = context.temp_dir.join("missing-python"); + let contents = fs_err::read_to_string(&pyvenv_cfg).unwrap(); + let contents = contents + .lines() + .map(|line| { + if line.starts_with("home = ") { + format!("home = {}", broken_home.simplified_display()) + } else { + line.to_string() + } + }) + .collect::>() + .join("\n"); + fs_err::write(&pyvenv_cfg, format!("{contents}\n")).unwrap(); + } // Reinstalling should skip the broken Python install. uv_snapshot!(context.filters(), context.tool_install()