mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Show resource and lockfile when waiting (#715)
We lock git checkout directories and the virtualenv to avoid two puffin instances running in parallel changing files at the same time and leading to a broken state. When one instance is blocking another, we need to inform the user (why is the program hanging?) and also add some information for them to debug the situation. The new messages will print ``` Waiting to acquire lock for /home/konsti/projects/puffin/.venv (lockfile: /home/konsti/projects/puffin/.venv/.lock) ``` or ``` Waiting to acquire lock for git+https://github.com/pydantic/pydantic-extra-types@0ce9f207a1e09a862287ab77512f0060c1625223 (lockfile: /home/konsti/projects/puffin/cache-all-kinds/git-v0/locks/f157fd329a506a34) ``` The messages aren't perfect but clear enough to see what the contention is and in the worst case to delete the lockfile. Fixes #714
This commit is contained in:
parent
e60f0ec732
commit
b7ad97a823
4 changed files with 15 additions and 5 deletions
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
|
||||
|
@ -85,6 +86,12 @@ impl Hash for CanonicalUrl {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for CanonicalUrl {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Like [`CanonicalUrl`], but attempts to represent an underlying source repository, abstracting
|
||||
/// away details like the specific commit or branch, or the subdirectory to build within the
|
||||
/// repository.
|
||||
|
|
|
@ -653,7 +653,8 @@ impl<'a, T: BuildContext> SourceDistCachedBuilder<'a, T> {
|
|||
// Avoid races between different processes, too.
|
||||
let lock_dir = git_dir.join("locks");
|
||||
fs::create_dir_all(&lock_dir).await?;
|
||||
let _lock = LockedFile::acquire(lock_dir.join(digest(&CanonicalUrl::new(url))))?;
|
||||
let canonical_url = CanonicalUrl::new(url);
|
||||
let _lock = LockedFile::acquire(lock_dir.join(digest(&canonical_url)), &canonical_url)?;
|
||||
|
||||
let DirectGitUrl { url, subdirectory } =
|
||||
DirectGitUrl::try_from(url).map_err(SourceDistError::Git)?;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::Display;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use fs2::FileExt;
|
||||
|
@ -99,14 +100,15 @@ pub fn directories(path: impl AsRef<Path>) -> impl Iterator<Item = PathBuf> {
|
|||
pub struct LockedFile(fs_err::File);
|
||||
|
||||
impl LockedFile {
|
||||
pub fn acquire(path: impl AsRef<Path>) -> Result<Self, std::io::Error> {
|
||||
pub fn acquire(path: impl AsRef<Path>, resource: impl Display) -> Result<Self, std::io::Error> {
|
||||
let file = fs_err::File::create(path.as_ref())?;
|
||||
match file.file().try_lock_exclusive() {
|
||||
Ok(()) => Ok(Self(file)),
|
||||
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
|
||||
warn_user!(
|
||||
"Waiting to acquire lock on {}",
|
||||
path.as_ref().parent().unwrap_or(path.as_ref()).display()
|
||||
"Waiting to acquire lock for {} (lockfile: {})",
|
||||
resource,
|
||||
path.as_ref().display()
|
||||
);
|
||||
file.file().lock_exclusive()?;
|
||||
Ok(Self(file))
|
||||
|
|
|
@ -104,7 +104,7 @@ impl Virtualenv {
|
|||
|
||||
/// Lock the virtual environment to prevent concurrent writes.
|
||||
pub fn lock(&self) -> Result<LockedFile, std::io::Error> {
|
||||
LockedFile::acquire(self.root.join(".lock"))
|
||||
LockedFile::acquire(self.root.join(".lock"), self.root.display())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue