mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Reinstall and recreate environments when interpreter is removed (#4935)
## Summary We now recreate the environment in `uv sync`, `uv tool install`, and `uv tool run` if the underlying interpreter has been removed. Closes https://github.com/astral-sh/uv/issues/4933.
This commit is contained in:
parent
53db63f6dd
commit
bb703b8343
4 changed files with 34 additions and 14 deletions
|
@ -11,7 +11,7 @@ use std::str::FromStr;
|
|||
|
||||
use fs_err::File;
|
||||
use thiserror::Error;
|
||||
use tracing::debug;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use install_wheel_rs::read_record_file;
|
||||
|
||||
|
@ -178,6 +178,9 @@ impl InstalledTools {
|
|||
}
|
||||
|
||||
/// Return the [`PythonEnvironment`] for a given tool, if it exists.
|
||||
///
|
||||
/// Returns `Ok(None)` if the environment does not exist or is linked to a non-existent
|
||||
/// interpreter.
|
||||
pub fn get_environment(
|
||||
&self,
|
||||
name: &PackageName,
|
||||
|
@ -186,15 +189,26 @@ impl InstalledTools {
|
|||
let _lock = self.acquire_lock();
|
||||
let environment_path = self.root.join(name.to_string());
|
||||
|
||||
if environment_path.is_dir() {
|
||||
match PythonEnvironment::from_root(&environment_path, cache) {
|
||||
Ok(venv) => {
|
||||
debug!(
|
||||
"Using existing environment for tool `{name}` at `{}`.",
|
||||
"Using existing environment for tool `{name}`: {}",
|
||||
environment_path.user_display()
|
||||
);
|
||||
Ok(Some(PythonEnvironment::from_root(environment_path, cache)?))
|
||||
} else {
|
||||
Ok(Some(venv))
|
||||
}
|
||||
Err(uv_python::Error::MissingEnvironment(_)) => Ok(None),
|
||||
Err(uv_python::Error::Query(uv_python::InterpreterError::NotFound(
|
||||
interpreter_path,
|
||||
))) => {
|
||||
warn!(
|
||||
"Ignoring existing virtual environment linked to non-existent Python interpreter: {}",
|
||||
interpreter_path.user_display()
|
||||
);
|
||||
Ok(None)
|
||||
}
|
||||
Err(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the [`PythonEnvironment`] for a given tool, removing any existing environments.
|
||||
|
@ -210,7 +224,7 @@ impl InstalledTools {
|
|||
match fs_err::remove_dir_all(&environment_path) {
|
||||
Ok(()) => {
|
||||
debug!(
|
||||
"Removed existing environment for tool `{name}` at `{}`.",
|
||||
"Removed existing environment for tool `{name}`: {}",
|
||||
environment_path.user_display()
|
||||
);
|
||||
}
|
||||
|
@ -219,7 +233,7 @@ impl InstalledTools {
|
|||
}
|
||||
|
||||
debug!(
|
||||
"Creating environment for tool `{name}` at `{}`.",
|
||||
"Creating environment for tool `{name}`: {}",
|
||||
environment_path.user_display()
|
||||
);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ use uv_python::{
|
|||
use uv_requirements::{NamedRequirementsResolver, RequirementsSpecification};
|
||||
use uv_resolver::{FlatIndex, OptionsBuilder, PythonRequirement, RequiresPython, ResolutionGraph};
|
||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy};
|
||||
use uv_warnings::warn_user;
|
||||
|
||||
use crate::commands::pip::operations::Modifications;
|
||||
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
|
||||
|
@ -174,6 +175,12 @@ impl FoundInterpreter {
|
|||
}
|
||||
}
|
||||
Err(uv_python::Error::MissingEnvironment(_)) => {}
|
||||
Err(uv_python::Error::Query(uv_python::InterpreterError::NotFound(path))) => {
|
||||
warn_user!(
|
||||
"Ignoring existing virtual environment linked to non-existent Python interpreter: {}",
|
||||
path.user_display().cyan()
|
||||
);
|
||||
}
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
|
||||
|
|
|
@ -166,9 +166,8 @@ pub(crate) async fn install(
|
|||
} else {
|
||||
let _ = writeln!(
|
||||
printer.stderr(),
|
||||
"Existing environment for `{}` does not satisfy the requested Python interpreter (`{}`)",
|
||||
"Existing environment for `{}` does not satisfy the requested Python interpreter",
|
||||
from.name,
|
||||
python_request
|
||||
);
|
||||
false
|
||||
}
|
||||
|
|
|
@ -1393,7 +1393,7 @@ fn tool_install_python_request() {
|
|||
|
||||
----- stderr -----
|
||||
warning: `uv tool install` is experimental and may change without warning.
|
||||
Existing environment for `black` does not satisfy the requested Python interpreter (`Python 3.11`)
|
||||
Existing environment for `black` does not satisfy the requested Python interpreter
|
||||
Resolved [N] packages in [TIME]
|
||||
Prepared [N] packages in [TIME]
|
||||
Installed [N] packages in [TIME]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue