Skip to content

Commit 7eb076a

Browse files
Force cache indexes to set hash digests and cache info (#15291)
## Summary Making it harder to accidentally omit these.
1 parent bcfa844 commit 7eb076a

File tree

3 files changed

+93
-76
lines changed

3 files changed

+93
-76
lines changed

crates/uv-distribution/src/index/built_wheel_index.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ use uv_distribution_types::{
1010
};
1111
use uv_normalize::PackageName;
1212
use uv_platform_tags::Tags;
13+
use uv_pypi_types::HashDigests;
1314
use uv_types::HashStrategy;
1415

1516
use crate::Error;
16-
use crate::index::cached_wheel::CachedWheel;
17+
use crate::index::cached_wheel::{CachedWheel, ResolvedWheel};
1718
use crate::source::{HTTP_REVISION, HttpRevisionPointer, LOCAL_REVISION, LocalRevisionPointer};
1819

1920
/// A local index of built distributions for a specific source distribution.
@@ -92,7 +93,9 @@ impl<'a> BuiltWheelIndex<'a> {
9293
)))
9394
};
9495

95-
Ok(self.find(&cache_shard))
96+
Ok(self.find(&cache_shard).map(|wheel| {
97+
CachedWheel::from_entry(wheel, revision.into_hashes(), CacheInfo::default())
98+
}))
9699
}
97100
/// Return the most compatible [`CachedWheel`] for a given source distribution at a local path.
98101
pub fn path(&self, source_dist: &PathSourceDist) -> Result<Option<CachedWheel>, Error> {
@@ -141,7 +144,7 @@ impl<'a> BuiltWheelIndex<'a> {
141144

142145
Ok(self
143146
.find(&cache_shard)
144-
.map(|wheel| wheel.with_cache_info(cache_info)))
147+
.map(|wheel| CachedWheel::from_entry(wheel, revision.into_hashes(), cache_info)))
145148
}
146149

147150
/// Return the most compatible [`CachedWheel`] for a given source distribution built from a
@@ -199,7 +202,7 @@ impl<'a> BuiltWheelIndex<'a> {
199202

200203
Ok(self
201204
.find(&cache_shard)
202-
.map(|wheel| wheel.with_cache_info(cache_info)))
205+
.map(|wheel| CachedWheel::from_entry(wheel, revision.into_hashes(), cache_info)))
203206
}
204207

205208
/// Return the most compatible [`CachedWheel`] for a given source distribution at a git URL.
@@ -234,6 +237,7 @@ impl<'a> BuiltWheelIndex<'a> {
234237
};
235238

236239
self.find(&cache_shard)
240+
.map(|wheel| CachedWheel::from_entry(wheel, HashDigests::empty(), CacheInfo::default()))
237241
}
238242

239243
/// Find the "best" distribution in the index for a given source distribution.
@@ -252,8 +256,8 @@ impl<'a> BuiltWheelIndex<'a> {
252256
/// ```
253257
///
254258
/// The `shard` should be `built-wheels-v0/pypi/django-allauth-0.51.0.tar.gz`.
255-
fn find(&self, shard: &CacheShard) -> Option<CachedWheel> {
256-
let mut candidate: Option<CachedWheel> = None;
259+
fn find(&self, shard: &CacheShard) -> Option<ResolvedWheel> {
260+
let mut candidate: Option<ResolvedWheel> = None;
257261

258262
// Unzipped wheels are stored as symlinks into the archive directory.
259263
for wheel_dir in uv_fs::entries(shard).ok().into_iter().flatten() {
@@ -265,7 +269,7 @@ impl<'a> BuiltWheelIndex<'a> {
265269
continue;
266270
}
267271

268-
match CachedWheel::from_built_source(&wheel_dir, self.cache) {
272+
match ResolvedWheel::from_built_source(&wheel_dir, self.cache) {
269273
None => {}
270274
Some(dist_info) => {
271275
// Pick the wheel with the highest priority

crates/uv-distribution/src/index/cached_wheel.rs

Lines changed: 74 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,14 @@ use crate::archive::Archive;
1313
use crate::{HttpArchivePointer, LocalArchivePointer};
1414

1515
#[derive(Debug, Clone)]
16-
pub struct CachedWheel {
16+
pub struct ResolvedWheel {
1717
/// The filename of the wheel.
1818
pub filename: WheelFilename,
1919
/// The [`CacheEntry`] for the wheel.
2020
pub entry: CacheEntry,
21-
/// The [`HashDigest`]s for the wheel.
22-
pub hashes: HashDigests,
23-
/// The [`CacheInfo`] for the wheel.
24-
pub cache_info: CacheInfo,
2521
}
2622

27-
impl CachedWheel {
23+
impl ResolvedWheel {
2824
/// Try to parse a distribution from a cached directory name (like `typing-extensions-4.8.0-py3-none-any`).
2925
pub fn from_built_source(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
3026
let path = path.as_ref();
@@ -36,10 +32,79 @@ impl CachedWheel {
3632
// Convert to a cached wheel.
3733
let archive = cache.resolve_link(path).ok()?;
3834
let entry = CacheEntry::from_path(archive);
39-
let hashes = HashDigests::empty();
40-
let cache_info = CacheInfo::default();
35+
Some(Self { filename, entry })
36+
}
37+
}
38+
39+
#[derive(Debug, Clone)]
40+
pub struct CachedWheel {
41+
/// The filename of the wheel.
42+
pub filename: WheelFilename,
43+
/// The [`CacheEntry`] for the wheel.
44+
pub entry: CacheEntry,
45+
/// The [`HashDigest`]s for the wheel.
46+
pub hashes: HashDigests,
47+
/// The [`CacheInfo`] for the wheel.
48+
pub cache_info: CacheInfo,
49+
}
50+
51+
impl CachedWheel {
52+
/// Create a [`CachedWheel`] from a [`ResolvedWheel`].
53+
pub fn from_entry(wheel: ResolvedWheel, hashes: HashDigests, cache_info: CacheInfo) -> Self {
54+
Self {
55+
filename: wheel.filename,
56+
entry: wheel.entry,
57+
hashes,
58+
cache_info,
59+
}
60+
}
61+
62+
/// Read a cached wheel from a `.http` pointer
63+
pub fn from_http_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
64+
let path = path.as_ref();
65+
66+
// Read the pointer.
67+
let pointer = HttpArchivePointer::read_from(path).ok()??;
68+
let cache_info = pointer.to_cache_info();
69+
let archive = pointer.into_archive();
70+
71+
// Ignore stale pointers.
72+
if !archive.exists(cache) {
73+
return None;
74+
}
75+
76+
let Archive { id, hashes, .. } = archive;
77+
let entry = cache.entry(CacheBucket::Archive, "", id);
78+
79+
// Convert to a cached wheel.
80+
Some(Self {
81+
filename: archive.filename,
82+
entry,
83+
hashes,
84+
cache_info,
85+
})
86+
}
87+
88+
/// Read a cached wheel from a `.rev` pointer
89+
pub fn from_local_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
90+
let path = path.as_ref();
91+
92+
// Read the pointer.
93+
let pointer = LocalArchivePointer::read_from(path).ok()??;
94+
let cache_info = pointer.to_cache_info();
95+
let archive = pointer.into_archive();
96+
97+
// Ignore stale pointers.
98+
if !archive.exists(cache) {
99+
return None;
100+
}
101+
102+
let Archive { id, hashes, .. } = archive;
103+
let entry = cache.entry(CacheBucket::Archive, "", id);
104+
105+
// Convert to a cached wheel.
41106
Some(Self {
42-
filename,
107+
filename: archive.filename,
43108
entry,
44109
hashes,
45110
cache_info,
@@ -115,64 +180,6 @@ impl CachedWheel {
115180
cache_info: self.cache_info,
116181
}
117182
}
118-
119-
/// Read a cached wheel from a `.http` pointer
120-
pub fn from_http_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
121-
let path = path.as_ref();
122-
123-
// Read the pointer.
124-
let pointer = HttpArchivePointer::read_from(path).ok()??;
125-
let cache_info = pointer.to_cache_info();
126-
let archive = pointer.into_archive();
127-
128-
// Ignore stale pointers.
129-
if !archive.exists(cache) {
130-
return None;
131-
}
132-
133-
let Archive { id, hashes, .. } = archive;
134-
let entry = cache.entry(CacheBucket::Archive, "", id);
135-
136-
// Convert to a cached wheel.
137-
Some(Self {
138-
filename: archive.filename,
139-
entry,
140-
hashes,
141-
cache_info,
142-
})
143-
}
144-
145-
/// Read a cached wheel from a `.rev` pointer
146-
pub fn from_local_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
147-
let path = path.as_ref();
148-
149-
// Read the pointer.
150-
let pointer = LocalArchivePointer::read_from(path).ok()??;
151-
let cache_info = pointer.to_cache_info();
152-
let archive = pointer.into_archive();
153-
154-
// Ignore stale pointers.
155-
if !archive.exists(cache) {
156-
return None;
157-
}
158-
159-
let Archive { id, hashes, .. } = archive;
160-
let entry = cache.entry(CacheBucket::Archive, "", id);
161-
162-
// Convert to a cached wheel.
163-
Some(Self {
164-
filename: archive.filename,
165-
entry,
166-
hashes,
167-
cache_info,
168-
})
169-
}
170-
171-
#[must_use]
172-
pub fn with_cache_info(mut self, cache_info: CacheInfo) -> Self {
173-
self.cache_info = cache_info;
174-
self
175-
}
176183
}
177184

178185
impl Hashed for CachedWheel {

crates/uv-distribution/src/index/registry_wheel_index.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::collections::hash_map::Entry;
44
use rustc_hash::{FxHashMap, FxHashSet};
55

66
use uv_cache::{Cache, CacheBucket, WheelCache};
7+
use uv_cache_info::CacheInfo;
78
use uv_cache_key::cache_digest;
89
use uv_distribution_types::{
910
BuildVariables, CachedRegistryDist, ConfigSettings, ExtraBuildRequirement, ExtraBuildRequires,
@@ -14,7 +15,7 @@ use uv_normalize::PackageName;
1415
use uv_platform_tags::Tags;
1516
use uv_types::HashStrategy;
1617

17-
use crate::index::cached_wheel::CachedWheel;
18+
use crate::index::cached_wheel::{CachedWheel, ResolvedWheel};
1819
use crate::source::{HTTP_REVISION, HttpRevisionPointer, LOCAL_REVISION, LocalRevisionPointer};
1920

2021
/// An entry in the [`RegistryWheelIndex`].
@@ -247,13 +248,18 @@ impl<'a> RegistryWheelIndex<'a> {
247248
continue;
248249
}
249250

250-
if let Some(wheel) = CachedWheel::from_built_source(wheel_dir, cache) {
251+
if let Some(wheel) = ResolvedWheel::from_built_source(wheel_dir, cache) {
251252
if wheel.filename.compatibility(tags).is_compatible() {
252253
// Enforce hash-checking based on the source distribution.
253254
if revision.satisfies(
254255
hasher
255256
.get_package(&wheel.filename.name, &wheel.filename.version),
256257
) {
258+
let wheel = CachedWheel::from_entry(
259+
wheel,
260+
revision.hashes().into(),
261+
CacheInfo::default(),
262+
);
257263
entries.push(IndexEntry {
258264
dist: wheel.into_registry_dist(),
259265
index,

0 commit comments

Comments
 (0)