Lock entire virtualenv during modifying commands (#695)

These commands all assume that the `site-packages` are constant
throughout.

Closes #691.
This commit is contained in:
Charlie Marsh 2023-12-18 16:44:45 -05:00 committed by GitHub
parent 207bb83a1c
commit 98fcb76015
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 53 additions and 39 deletions

View file

@ -1,12 +1,7 @@
use std::io;
use std::path::PathBuf;
use std::sync::Arc;
use fs2::FileExt;
use fs_err::File;
use rustc_hash::FxHashMap;
use tokio::sync::Mutex;
use tracing::error;
use distribution_types::{Identifier, ResourceId};
@ -23,29 +18,3 @@ impl Locks {
.clone()
}
}
/// A file lock that is automatically released when dropped.
#[derive(Debug)]
pub(crate) struct LockedFile(File);
impl LockedFile {
pub(crate) fn new(path: impl Into<PathBuf>) -> Result<Self, io::Error> {
let file = File::create(path)?;
// TODO(konstin): Notify the user when the lock isn't free so they know why nothing is
// happening
file.file().lock_exclusive()?;
Ok(Self(file))
}
}
impl Drop for LockedFile {
fn drop(&mut self) {
if let Err(err) = self.0.file().unlock() {
error!(
"Failed to unlock {}; program may be stuck: {}",
self.0.path().display(),
err
);
}
}
}

View file

@ -30,13 +30,12 @@ use puffin_cache::{
digest, CacheBucket, CacheEntry, CacheShard, CachedByTimestamp, CanonicalUrl, WheelCache,
};
use puffin_client::{CachedClient, CachedClientError, DataWithCachePolicy};
use puffin_fs::write_atomic;
use puffin_fs::{write_atomic, LockedFile};
use puffin_git::{Fetch, GitSource};
use puffin_normalize::PackageName;
use puffin_traits::{BuildContext, BuildKind, SourceBuildTrait};
use pypi_types::Metadata21;
use crate::locks::LockedFile;
use crate::Reporter;
/// The caller is responsible for adding the source dist information to the error chain
@ -652,9 +651,9 @@ impl<'a, T: BuildContext> SourceDistCachedBuilder<'a, T> {
let git_dir = self.build_context.cache().bucket(CacheBucket::Git);
// Avoid races between different processes, too.
let locks_dir = git_dir.join("locks");
fs::create_dir_all(&locks_dir).await?;
let _lockfile = LockedFile::new(locks_dir.join(digest(&CanonicalUrl::new(url))))?;
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 DirectGitUrl { url, subdirectory } =
DirectGitUrl::try_from(url).map_err(SourceDistError::Git)?;