diff --git a/crates/uv-build-frontend/src/lib.rs b/crates/uv-build-frontend/src/lib.rs index 524cb96c0..1ef439788 100644 --- a/crates/uv-build-frontend/src/lib.rs +++ b/crates/uv-build-frontend/src/lib.rs @@ -359,7 +359,9 @@ impl SourceBuild { interpreter.clone(), uv_virtualenv::Prompt::None, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::TemporaryEnvironment, + ), false, false, false, diff --git a/crates/uv-tool/src/lib.rs b/crates/uv-tool/src/lib.rs index 2702fda6e..d1330efe3 100644 --- a/crates/uv-tool/src/lib.rs +++ b/crates/uv-tool/src/lib.rs @@ -273,7 +273,7 @@ impl InstalledTools { interpreter, uv_virtualenv::Prompt::None, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove(uv_virtualenv::RemovalReason::ManagedEnvironment), false, false, false, diff --git a/crates/uv-virtualenv/src/lib.rs b/crates/uv-virtualenv/src/lib.rs index bf06c331f..f15977f92 100644 --- a/crates/uv-virtualenv/src/lib.rs +++ b/crates/uv-virtualenv/src/lib.rs @@ -6,7 +6,7 @@ use thiserror::Error; use uv_preview::Preview; use uv_python::{Interpreter, PythonEnvironment}; -pub use virtualenv::{OnExisting, remove_virtualenv}; +pub use virtualenv::{OnExisting, RemovalReason, remove_virtualenv}; mod virtualenv; diff --git a/crates/uv-virtualenv/src/virtualenv.rs b/crates/uv-virtualenv/src/virtualenv.rs index 63122d1fe..1a91acdc5 100644 --- a/crates/uv-virtualenv/src/virtualenv.rs +++ b/crates/uv-virtualenv/src/virtualenv.rs @@ -136,8 +136,8 @@ pub(crate) fn create( OnExisting::Allow => { debug!("Allowing existing {name} due to `--allow-existing`"); } - OnExisting::Remove => { - debug!("Removing existing {name} due to `--clear`"); + OnExisting::Remove(reason) => { + debug!("Removing existing {name} ({reason})"); // Before removing the virtual environment, we need to canonicalize the path // because `Path::metadata` will follow the symlink but we're still operating on // the unresolved path and will remove the symlink itself. @@ -634,6 +634,28 @@ pub fn remove_virtualenv(location: &Path) -> Result<(), Error> { Ok(()) } +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum RemovalReason { + /// The removal was explicitly requested, i.e., with `--clear`. + UserRequest, + /// The environment can be removed because it is considered temporary, e.g., a build + /// environment. + TemporaryEnvironment, + /// The environment can be removed because it is managed by uv, e.g., a project or tool + /// environment. + ManagedEnvironment, +} + +impl std::fmt::Display for RemovalReason { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UserRequest => f.write_str("requested with `--clear`"), + Self::ManagedEnvironment => f.write_str("environment is managed by uv"), + Self::TemporaryEnvironment => f.write_str("environment is temporary"), + } + } +} + #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] pub enum OnExisting { /// Prompt before removing an existing directory. @@ -647,7 +669,7 @@ pub enum OnExisting { /// files in the directory. Allow, /// Remove an existing directory. - Remove, + Remove(RemovalReason), } impl OnExisting { @@ -655,7 +677,7 @@ impl OnExisting { if allow_existing { Self::Allow } else if clear { - Self::Remove + Self::Remove(RemovalReason::UserRequest) } else if no_clear { Self::Fail } else { diff --git a/crates/uv/src/commands/project/environment.rs b/crates/uv/src/commands/project/environment.rs index cfef02018..e8ecc6bc6 100644 --- a/crates/uv/src/commands/project/environment.rs +++ b/crates/uv/src/commands/project/environment.rs @@ -187,7 +187,7 @@ impl CachedEnvironment { interpreter, uv_virtualenv::Prompt::None, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove(uv_virtualenv::RemovalReason::TemporaryEnvironment), true, false, false, diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index 85ec65d78..2644402ee 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -1368,7 +1368,9 @@ impl ProjectEnvironment { interpreter, prompt, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::ManagedEnvironment, + ), false, false, upgradeable, @@ -1408,7 +1410,9 @@ impl ProjectEnvironment { interpreter, prompt, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::ManagedEnvironment, + ), false, false, upgradeable, @@ -1560,7 +1564,9 @@ impl ScriptEnvironment { interpreter, prompt, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::ManagedEnvironment, + ), false, false, upgradeable, @@ -1600,7 +1606,9 @@ impl ScriptEnvironment { interpreter, prompt, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::ManagedEnvironment, + ), false, false, upgradeable, diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index 3101cee81..f3ed2443c 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -481,7 +481,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl interpreter, uv_virtualenv::Prompt::None, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::TemporaryEnvironment, + ), false, false, false, @@ -681,7 +683,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl interpreter, uv_virtualenv::Prompt::None, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::TemporaryEnvironment, + ), false, false, false, @@ -914,7 +918,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl interpreter, uv_virtualenv::Prompt::None, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::TemporaryEnvironment, + ), false, false, false, @@ -1040,7 +1046,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl base_interpreter.clone(), uv_virtualenv::Prompt::None, false, - uv_virtualenv::OnExisting::Remove, + uv_virtualenv::OnExisting::Remove( + uv_virtualenv::RemovalReason::TemporaryEnvironment, + ), false, false, false,