Refuse to remove non-virtual environments in uv venv (#15538)
Some checks are pending
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | aarch64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | pyenv on wsl x86-64 (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
zizmor / Run zizmor (push) Waiting to run

## Summary

Closes https://github.com/astral-sh/uv/issues/15474.
This commit is contained in:
Charlie Marsh 2025-08-26 13:26:20 -04:00 committed by GitHub
parent 0c674619b2
commit 9eb5fc240c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 55 additions and 10 deletions

View file

@ -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

View file

@ -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
"
);