mirror of https://github.com/astral-sh/uv
Use a flock to avoid concurrent initialization of project environments (#11259)
## Summary If you `uv run` from the same directory via multiple processes at the same time, some of them will fail as they'll see an "incomplete" virtual environment. Closes https://github.com/astral-sh/uv/issues/11219.
This commit is contained in:
parent
239f3d76b9
commit
311a96bd28
|
|
@ -8,6 +8,7 @@ use owo_colors::OwoColorize;
|
|||
use tracing::debug;
|
||||
|
||||
use uv_cache::Cache;
|
||||
use uv_cache_key::cache_digest;
|
||||
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
Concurrency, Constraints, DevGroupsManifest, DevGroupsSpecification, ExtrasSpecification,
|
||||
|
|
@ -18,7 +19,7 @@ use uv_distribution::DistributionDatabase;
|
|||
use uv_distribution_types::{
|
||||
Index, Resolution, UnresolvedRequirement, UnresolvedRequirementSpecification,
|
||||
};
|
||||
use uv_fs::{Simplified, CWD};
|
||||
use uv_fs::{LockedFile, Simplified, CWD};
|
||||
use uv_git::ResolvedRepositoryReference;
|
||||
use uv_installer::{SatisfiesResult, SitePackages};
|
||||
use uv_normalize::{GroupName, PackageName, DEV_DEPENDENCIES};
|
||||
|
|
@ -743,6 +744,18 @@ impl ProjectInterpreter {
|
|||
ProjectInterpreter::Environment(venv) => venv.into_interpreter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Grab a file lock for the environment to prevent concurrent writes across processes.
|
||||
pub(crate) async fn lock(workspace: &Workspace) -> Result<LockedFile, std::io::Error> {
|
||||
LockedFile::acquire(
|
||||
std::env::temp_dir().join(format!(
|
||||
"uv-{}.lock",
|
||||
cache_digest(workspace.install_path())
|
||||
)),
|
||||
workspace.install_path().user_display(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// The source of a `Requires-Python` specifier.
|
||||
|
|
@ -929,6 +942,9 @@ pub(crate) async fn get_or_init_environment(
|
|||
cache: &Cache,
|
||||
printer: Printer,
|
||||
) -> Result<PythonEnvironment, ProjectError> {
|
||||
// Lock the project environment to avoid synchronization issues.
|
||||
let _lock = ProjectInterpreter::lock(workspace).await?;
|
||||
|
||||
match ProjectInterpreter::discover(
|
||||
workspace,
|
||||
workspace.install_path().as_ref(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue