diff --git a/crates/uv-virtualenv/src/virtualenv.rs b/crates/uv-virtualenv/src/virtualenv.rs index cf440a212..0075526f0 100644 --- a/crates/uv-virtualenv/src/virtualenv.rs +++ b/crates/uv-virtualenv/src/virtualenv.rs @@ -110,7 +110,8 @@ pub(crate) fn create( ); } Ok(metadata) if metadata.is_dir() => { - let name = if uv_fs::is_virtualenv_base(location) { + let is_virtualenv = uv_fs::is_virtualenv_base(location); + let name = if is_virtualenv { "virtual environment" } else { "directory" @@ -131,7 +132,14 @@ pub(crate) fn create( fs::create_dir_all(&location)?; } OnExisting::Fail => { - match confirm_clear(location, name)? { + let confirmation = if is_virtualenv { + confirm_clear(location, name)? + } else { + // Refuse to remove a non-virtual environment; don't even prompt. + Some(false) + }; + + match confirmation { Some(true) => { debug!("Removing existing {name} due to confirmation"); // Before removing the virtual environment, we need to canonicalize the diff --git a/crates/uv/tests/it/venv.rs b/crates/uv/tests/it/venv.rs index d7db5554e..3cd796f16 100644 --- a/crates/uv/tests/it/venv.rs +++ b/crates/uv/tests/it/venv.rs @@ -958,7 +958,8 @@ fn empty_dir_exists() -> Result<()> { fn non_empty_dir_exists() -> Result<()> { let context = TestContext::new_with_versions(&["3.12"]); - // Create a non-empty directory at `.venv`. Creating a virtualenv at the same path should fail. + // Create a non-empty directory at `.venv`. Creating a virtualenv at the same path should fail, + // unless `--clear` is specified. context.venv.create_dir_all()?; context.venv.child("file").touch()?; @@ -966,6 +967,25 @@ fn non_empty_dir_exists() -> Result<()> { .arg(context.venv.as_os_str()) .arg("--python") .arg("3.12"), @r" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + Using CPython 3.12.[X] interpreter at: [PYTHON-3.12] + Creating virtual environment at: .venv + error: Failed to create virtual environment + Caused by: A directory already exists at: .venv + + hint: Use the `--clear` flag or set `UV_VENV_CLEAR=1` to replace the existing directory + " + ); + + uv_snapshot!(context.filters(), context.venv() + .arg(context.venv.as_os_str()) + .arg("--clear") + .arg("--python") + .arg("3.12"), @r" success: true exit_code: 0 ----- stdout ----- @@ -973,7 +993,6 @@ fn non_empty_dir_exists() -> Result<()> { ----- stderr ----- Using CPython 3.12.[X] interpreter at: [PYTHON-3.12] Creating virtual environment at: .venv - warning: A directory already exists at `.venv`. In the future, uv will require `--clear` to replace it Activate with: source .venv/[BIN]/activate " ); @@ -994,15 +1013,17 @@ fn non_empty_dir_exists_allow_existing() -> Result<()> { .arg(context.venv.as_os_str()) .arg("--python") .arg("3.12"), @r" - success: true - exit_code: 0 + success: false + exit_code: 2 ----- stdout ----- ----- stderr ----- Using CPython 3.12.[X] interpreter at: [PYTHON-3.12] Creating virtual environment at: .venv - warning: A directory already exists at `.venv`. In the future, uv will require `--clear` to replace it - Activate with: source .venv/[BIN]/activate + error: Failed to create virtual environment + Caused by: A directory already exists at: .venv + + hint: Use the `--clear` flag or set `UV_VENV_CLEAR=1` to replace the existing directory " ); @@ -1578,17 +1599,33 @@ fn create_venv_current_working_directory() { let context = TestContext::new_with_versions(&["3.12"]); uv_snapshot!(context.filters(), context.venv() - .arg(".") + .arg(context.venv.as_os_str()) .arg("--python") .arg("3.12"), @r" success: true exit_code: 0 ----- stdout ----- + ----- stderr ----- + Using CPython 3.12.[X] interpreter at: [PYTHON-3.12] + Creating virtual environment at: .venv + Activate with: source .venv/[BIN]/activate + " + ); + + uv_snapshot!(context.filters(), context.venv() + .arg(".") + .arg("--clear") + .arg("--python") + .arg("3.12") + .current_dir(&context.venv), @r" + success: true + exit_code: 0 + ----- stdout ----- + ----- stderr ----- Using CPython 3.12.[X] interpreter at: [PYTHON-3.12] Creating virtual environment at: . - warning: A directory already exists at `.`. In the future, uv will require `--clear` to replace it Activate with: source bin/activate " );