Allow --force to overwrite existing virtualenv (#2548)

## Summary

Closes https://github.com/astral-sh/uv/issues/2529.

## Test Plan

- `mkdir .venv`
- `touch .venv/foo`
- `cargo run venv` (ensure failure)
- `cargo run venv --force` (ensure success)
- `cargo run venv --force` (ensure success again)
This commit is contained in:
Charlie Marsh 2024-05-01 09:34:52 -07:00 committed by GitHub
parent 630d3fde5c
commit 614c07329b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 127 additions and 41 deletions

View file

@ -47,6 +47,7 @@ pub fn create_bare_venv(
interpreter: &Interpreter,
prompt: Prompt,
system_site_packages: bool,
force: bool,
) -> Result<Virtualenv, Error> {
// Determine the base Python executable; that is, the Python executable that should be
// considered the "base" for the virtual environment. This is typically the Python executable
@ -88,7 +89,9 @@ pub fn create_bare_venv(
format!("File exists at `{}`", location.user_display()),
)));
} else if metadata.is_dir() {
if location.join("pyvenv.cfg").is_file() {
if force {
info!("Overwriting existing directory");
} else if location.join("pyvenv.cfg").is_file() {
info!("Removing existing directory");
fs::remove_dir_all(location)?;
fs::create_dir_all(location)?;
@ -147,19 +150,17 @@ pub fn create_bare_venv(
})?;
// Different names for the python interpreter
fs::create_dir(&scripts)?;
fs::create_dir_all(&scripts)?;
let executable = scripts.join(format!("python{EXE_SUFFIX}"));
#[cfg(unix)]
{
use fs_err::os::unix::fs::symlink;
symlink(&base_python, &executable)?;
symlink(
uv_fs::replace_symlink(&base_python, &executable)?;
uv_fs::replace_symlink(
"python",
scripts.join(format!("python{}", interpreter.python_major())),
)?;
symlink(
uv_fs::replace_symlink(
"python",
scripts.join(format!(
"python{}.{}",

View file

@ -51,9 +51,10 @@ pub fn create_venv(
interpreter: Interpreter,
prompt: Prompt,
system_site_packages: bool,
force: bool,
) -> Result<PythonEnvironment, Error> {
// Create the virtualenv at the given location.
let virtualenv = create_bare_venv(location, &interpreter, prompt, system_site_packages)?;
let virtualenv = create_bare_venv(location, &interpreter, prompt, system_site_packages, force)?;
// Create the corresponding `PythonEnvironment`.
let interpreter = interpreter.with_virtualenv(virtualenv);

View file

@ -46,6 +46,7 @@ fn run() -> Result<(), uv_virtualenv::Error> {
&interpreter,
Prompt::from_args(cli.prompt),
cli.system_site_packages,
false,
)?;
Ok(())
}