From eda9cb31cdfa07d4a61875043bdaf6151edb5d9c Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sat, 11 May 2024 13:15:58 -0400 Subject: [PATCH] Apply advisory locks when building source distributions --- crates/uv-cache/src/lib.rs | 6 ++++++ crates/uv-distribution/src/source/mod.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/crates/uv-cache/src/lib.rs b/crates/uv-cache/src/lib.rs index 3805d6cf8d3..1e840f23fc3 100644 --- a/crates/uv-cache/src/lib.rs +++ b/crates/uv-cache/src/lib.rs @@ -94,6 +94,12 @@ impl CacheShard { pub fn shard(&self, dir: impl AsRef) -> Self { Self(self.0.join(dir.as_ref())) } + + /// Acquire a lock on the shard. + pub fn lock(&self) -> io::Result { + fs_err::create_dir_all(&self.0)?; + uv_fs::LockedFile::acquire(self.0.join(".lock"), self.0.display()) + } } impl AsRef for CacheShard { diff --git a/crates/uv-distribution/src/source/mod.rs b/crates/uv-distribution/src/source/mod.rs index 9d12385b817..70c6ab82dc9 100644 --- a/crates/uv-distribution/src/source/mod.rs +++ b/crates/uv-distribution/src/source/mod.rs @@ -396,6 +396,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { hashes: HashPolicy<'_>, client: &ManagedClient<'_>, ) -> Result { + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // Fetch the revision for the source distribution. let revision = self .url_revision(source, filename, url, cache_shard, hashes, client) @@ -465,6 +467,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { hashes: HashPolicy<'_>, client: &ManagedClient<'_>, ) -> Result { + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // Fetch the revision for the source distribution. let revision = self .url_revision(source, filename, url, cache_shard, hashes, client) @@ -625,6 +629,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { tags: &Tags, hashes: HashPolicy<'_>, ) -> Result { + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // Fetch the revision for the source distribution. let revision = self .archive_revision(source, resource, cache_shard, hashes) @@ -691,6 +697,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { cache_shard: &CacheShard, hashes: HashPolicy<'_>, ) -> Result { + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // Fetch the revision for the source distribution. let revision = self .archive_revision(source, resource, cache_shard, hashes) @@ -838,6 +846,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { WheelCache::Path(resource.url).root(), ); + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // Fetch the revision for the source distribution. let revision = self .source_tree_revision(source, resource, &cache_shard) @@ -902,6 +912,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { WheelCache::Path(resource.url).root(), ); + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // Fetch the revision for the source distribution. let revision = self .source_tree_revision(source, resource, &cache_shard) @@ -1039,6 +1051,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { WheelCache::Git(&url, &git_sha.to_short_string()).root(), ); + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // If the cache contains a compatible wheel, return it. if let Some(built_wheel) = BuiltWheelMetadata::find_in_cache(tags, &cache_shard) { return Ok(built_wheel); @@ -1111,6 +1125,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { WheelCache::Git(&url, &git_sha.to_short_string()).root(), ); + let _lock = cache_shard.lock().map_err(Error::CacheWrite)?; + // If the cache contains compatible metadata, return it. let metadata_entry = cache_shard.entry(METADATA); if self