Guard against self-deletion in `uv venv` and `uv tool` (#10206)

## Summary

Closes https://github.com/astral-sh/uv/issues/1327.
This commit is contained in:
Charlie Marsh 2024-12-29 10:46:45 -05:00 committed by GitHub
parent 4b5a89dbff
commit cecff3a726
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 31 additions and 4 deletions

2
Cargo.lock generated
View File

@ -5558,6 +5558,7 @@ version = "0.0.1"
dependencies = [
"fs-err 3.0.0",
"pathdiff",
"self-replace",
"serde",
"thiserror 2.0.9",
"toml",
@ -5624,6 +5625,7 @@ dependencies = [
"fs-err 3.0.0",
"itertools 0.13.0",
"pathdiff",
"self-replace",
"thiserror 2.0.9",
"tracing",
"uv-fs",

View File

@ -29,6 +29,7 @@ uv-settings = { workspace = true }
uv-state = { workspace = true }
uv-static = { workspace = true }
uv-virtualenv = { workspace = true }
fs-err = { workspace = true }
pathdiff = { workspace = true }
serde = { workspace = true }
@ -36,3 +37,6 @@ thiserror = { workspace = true }
toml = { workspace = true }
toml_edit = { workspace = true }
tracing = { workspace = true }
[target.'cfg(target_os = "windows")'.dependencies]
self-replace = { workspace = true }

View File

@ -184,8 +184,16 @@ impl InstalledTools {
environment_path.user_display()
);
// TODO(charlie): On Windows, if the current executable is in the directory,
// we need to use `safe_delete`.
// On Windows, if the current executable is in the directory, guard against self-deletion.
#[cfg(windows)]
if let Ok(itself) = std::env::current_exe() {
let target = std::path::absolute(&environment_path)?;
if itself.starts_with(&target) {
debug!("Detected self-delete of executable: {}", itself.display());
self_replace::self_delete_outside_path(&environment_path)?;
}
}
fs_err::remove_dir_all(environment_path)?;
Ok(())

View File

@ -32,3 +32,6 @@ itertools = { workspace = true }
pathdiff = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
[target.'cfg(target_os = "windows")'.dependencies]
self-replace = { workspace = true }

View File

@ -105,9 +105,19 @@ pub(crate) fn create(
if allow_existing {
debug!("Allowing existing directory");
} else if location.join("pyvenv.cfg").is_file() {
// TODO(charlie): On Windows, if the current executable is in the directory,
// we need to use `safe_delete`.
debug!("Removing existing directory");
// On Windows, if the current executable is in the directory, guard against
// self-deletion.
#[cfg(windows)]
if let Ok(itself) = std::env::current_exe() {
let target = std::path::absolute(location)?;
if itself.starts_with(&target) {
debug!("Detected self-delete of executable: {}", itself.display());
self_replace::self_delete_outside_path(location)?;
}
}
fs::remove_dir_all(location)?;
fs::create_dir_all(location)?;
} else if location