mirror of https://github.com/astral-sh/uv
Force cache indexes to set hash digests and cache info (#15291)
## Summary Making it harder to accidentally omit these.
This commit is contained in:
parent
bcfa8443da
commit
7eb076aaef
|
|
@ -10,10 +10,11 @@ use uv_distribution_types::{
|
|||
};
|
||||
use uv_normalize::PackageName;
|
||||
use uv_platform_tags::Tags;
|
||||
use uv_pypi_types::HashDigests;
|
||||
use uv_types::HashStrategy;
|
||||
|
||||
use crate::Error;
|
||||
use crate::index::cached_wheel::CachedWheel;
|
||||
use crate::index::cached_wheel::{CachedWheel, ResolvedWheel};
|
||||
use crate::source::{HTTP_REVISION, HttpRevisionPointer, LOCAL_REVISION, LocalRevisionPointer};
|
||||
|
||||
/// A local index of built distributions for a specific source distribution.
|
||||
|
|
@ -92,7 +93,9 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
)))
|
||||
};
|
||||
|
||||
Ok(self.find(&cache_shard))
|
||||
Ok(self.find(&cache_shard).map(|wheel| {
|
||||
CachedWheel::from_entry(wheel, revision.into_hashes(), CacheInfo::default())
|
||||
}))
|
||||
}
|
||||
/// Return the most compatible [`CachedWheel`] for a given source distribution at a local path.
|
||||
pub fn path(&self, source_dist: &PathSourceDist) -> Result<Option<CachedWheel>, Error> {
|
||||
|
|
@ -141,7 +144,7 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
|
||||
Ok(self
|
||||
.find(&cache_shard)
|
||||
.map(|wheel| wheel.with_cache_info(cache_info)))
|
||||
.map(|wheel| CachedWheel::from_entry(wheel, revision.into_hashes(), cache_info)))
|
||||
}
|
||||
|
||||
/// Return the most compatible [`CachedWheel`] for a given source distribution built from a
|
||||
|
|
@ -199,7 +202,7 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
|
||||
Ok(self
|
||||
.find(&cache_shard)
|
||||
.map(|wheel| wheel.with_cache_info(cache_info)))
|
||||
.map(|wheel| CachedWheel::from_entry(wheel, revision.into_hashes(), cache_info)))
|
||||
}
|
||||
|
||||
/// Return the most compatible [`CachedWheel`] for a given source distribution at a git URL.
|
||||
|
|
@ -234,6 +237,7 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
};
|
||||
|
||||
self.find(&cache_shard)
|
||||
.map(|wheel| CachedWheel::from_entry(wheel, HashDigests::empty(), CacheInfo::default()))
|
||||
}
|
||||
|
||||
/// Find the "best" distribution in the index for a given source distribution.
|
||||
|
|
@ -252,8 +256,8 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
/// ```
|
||||
///
|
||||
/// The `shard` should be `built-wheels-v0/pypi/django-allauth-0.51.0.tar.gz`.
|
||||
fn find(&self, shard: &CacheShard) -> Option<CachedWheel> {
|
||||
let mut candidate: Option<CachedWheel> = None;
|
||||
fn find(&self, shard: &CacheShard) -> Option<ResolvedWheel> {
|
||||
let mut candidate: Option<ResolvedWheel> = None;
|
||||
|
||||
// Unzipped wheels are stored as symlinks into the archive directory.
|
||||
for wheel_dir in uv_fs::entries(shard).ok().into_iter().flatten() {
|
||||
|
|
@ -265,7 +269,7 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
continue;
|
||||
}
|
||||
|
||||
match CachedWheel::from_built_source(&wheel_dir, self.cache) {
|
||||
match ResolvedWheel::from_built_source(&wheel_dir, self.cache) {
|
||||
None => {}
|
||||
Some(dist_info) => {
|
||||
// Pick the wheel with the highest priority
|
||||
|
|
|
|||
|
|
@ -12,6 +12,30 @@ use uv_pypi_types::{HashDigest, HashDigests, VerbatimParsedUrl};
|
|||
use crate::archive::Archive;
|
||||
use crate::{HttpArchivePointer, LocalArchivePointer};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ResolvedWheel {
|
||||
/// The filename of the wheel.
|
||||
pub filename: WheelFilename,
|
||||
/// The [`CacheEntry`] for the wheel.
|
||||
pub entry: CacheEntry,
|
||||
}
|
||||
|
||||
impl ResolvedWheel {
|
||||
/// Try to parse a distribution from a cached directory name (like `typing-extensions-4.8.0-py3-none-any`).
|
||||
pub fn from_built_source(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
|
||||
let path = path.as_ref();
|
||||
|
||||
// Determine the wheel filename.
|
||||
let filename = path.file_name()?.to_str()?;
|
||||
let filename = WheelFilename::from_stem(filename).ok()?;
|
||||
|
||||
// Convert to a cached wheel.
|
||||
let archive = cache.resolve_link(path).ok()?;
|
||||
let entry = CacheEntry::from_path(archive);
|
||||
Some(Self { filename, entry })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CachedWheel {
|
||||
/// The filename of the wheel.
|
||||
|
|
@ -25,21 +49,62 @@ pub struct CachedWheel {
|
|||
}
|
||||
|
||||
impl CachedWheel {
|
||||
/// Try to parse a distribution from a cached directory name (like `typing-extensions-4.8.0-py3-none-any`).
|
||||
pub fn from_built_source(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
|
||||
/// Create a [`CachedWheel`] from a [`ResolvedWheel`].
|
||||
pub fn from_entry(wheel: ResolvedWheel, hashes: HashDigests, cache_info: CacheInfo) -> Self {
|
||||
Self {
|
||||
filename: wheel.filename,
|
||||
entry: wheel.entry,
|
||||
hashes,
|
||||
cache_info,
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a cached wheel from a `.http` pointer
|
||||
pub fn from_http_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
|
||||
let path = path.as_ref();
|
||||
|
||||
// Determine the wheel filename.
|
||||
let filename = path.file_name()?.to_str()?;
|
||||
let filename = WheelFilename::from_stem(filename).ok()?;
|
||||
// Read the pointer.
|
||||
let pointer = HttpArchivePointer::read_from(path).ok()??;
|
||||
let cache_info = pointer.to_cache_info();
|
||||
let archive = pointer.into_archive();
|
||||
|
||||
// Ignore stale pointers.
|
||||
if !archive.exists(cache) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let Archive { id, hashes, .. } = archive;
|
||||
let entry = cache.entry(CacheBucket::Archive, "", id);
|
||||
|
||||
// Convert to a cached wheel.
|
||||
let archive = cache.resolve_link(path).ok()?;
|
||||
let entry = CacheEntry::from_path(archive);
|
||||
let hashes = HashDigests::empty();
|
||||
let cache_info = CacheInfo::default();
|
||||
Some(Self {
|
||||
filename,
|
||||
filename: archive.filename,
|
||||
entry,
|
||||
hashes,
|
||||
cache_info,
|
||||
})
|
||||
}
|
||||
|
||||
/// Read a cached wheel from a `.rev` pointer
|
||||
pub fn from_local_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
|
||||
let path = path.as_ref();
|
||||
|
||||
// Read the pointer.
|
||||
let pointer = LocalArchivePointer::read_from(path).ok()??;
|
||||
let cache_info = pointer.to_cache_info();
|
||||
let archive = pointer.into_archive();
|
||||
|
||||
// Ignore stale pointers.
|
||||
if !archive.exists(cache) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let Archive { id, hashes, .. } = archive;
|
||||
let entry = cache.entry(CacheBucket::Archive, "", id);
|
||||
|
||||
// Convert to a cached wheel.
|
||||
Some(Self {
|
||||
filename: archive.filename,
|
||||
entry,
|
||||
hashes,
|
||||
cache_info,
|
||||
|
|
@ -115,64 +180,6 @@ impl CachedWheel {
|
|||
cache_info: self.cache_info,
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a cached wheel from a `.http` pointer
|
||||
pub fn from_http_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
|
||||
let path = path.as_ref();
|
||||
|
||||
// Read the pointer.
|
||||
let pointer = HttpArchivePointer::read_from(path).ok()??;
|
||||
let cache_info = pointer.to_cache_info();
|
||||
let archive = pointer.into_archive();
|
||||
|
||||
// Ignore stale pointers.
|
||||
if !archive.exists(cache) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let Archive { id, hashes, .. } = archive;
|
||||
let entry = cache.entry(CacheBucket::Archive, "", id);
|
||||
|
||||
// Convert to a cached wheel.
|
||||
Some(Self {
|
||||
filename: archive.filename,
|
||||
entry,
|
||||
hashes,
|
||||
cache_info,
|
||||
})
|
||||
}
|
||||
|
||||
/// Read a cached wheel from a `.rev` pointer
|
||||
pub fn from_local_pointer(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
|
||||
let path = path.as_ref();
|
||||
|
||||
// Read the pointer.
|
||||
let pointer = LocalArchivePointer::read_from(path).ok()??;
|
||||
let cache_info = pointer.to_cache_info();
|
||||
let archive = pointer.into_archive();
|
||||
|
||||
// Ignore stale pointers.
|
||||
if !archive.exists(cache) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let Archive { id, hashes, .. } = archive;
|
||||
let entry = cache.entry(CacheBucket::Archive, "", id);
|
||||
|
||||
// Convert to a cached wheel.
|
||||
Some(Self {
|
||||
filename: archive.filename,
|
||||
entry,
|
||||
hashes,
|
||||
cache_info,
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_cache_info(mut self, cache_info: CacheInfo) -> Self {
|
||||
self.cache_info = cache_info;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Hashed for CachedWheel {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::collections::hash_map::Entry;
|
|||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use uv_cache::{Cache, CacheBucket, WheelCache};
|
||||
use uv_cache_info::CacheInfo;
|
||||
use uv_cache_key::cache_digest;
|
||||
use uv_distribution_types::{
|
||||
BuildVariables, CachedRegistryDist, ConfigSettings, ExtraBuildRequirement, ExtraBuildRequires,
|
||||
|
|
@ -14,7 +15,7 @@ use uv_normalize::PackageName;
|
|||
use uv_platform_tags::Tags;
|
||||
use uv_types::HashStrategy;
|
||||
|
||||
use crate::index::cached_wheel::CachedWheel;
|
||||
use crate::index::cached_wheel::{CachedWheel, ResolvedWheel};
|
||||
use crate::source::{HTTP_REVISION, HttpRevisionPointer, LOCAL_REVISION, LocalRevisionPointer};
|
||||
|
||||
/// An entry in the [`RegistryWheelIndex`].
|
||||
|
|
@ -247,13 +248,18 @@ impl<'a> RegistryWheelIndex<'a> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Some(wheel) = CachedWheel::from_built_source(wheel_dir, cache) {
|
||||
if let Some(wheel) = ResolvedWheel::from_built_source(wheel_dir, cache) {
|
||||
if wheel.filename.compatibility(tags).is_compatible() {
|
||||
// Enforce hash-checking based on the source distribution.
|
||||
if revision.satisfies(
|
||||
hasher
|
||||
.get_package(&wheel.filename.name, &wheel.filename.version),
|
||||
) {
|
||||
let wheel = CachedWheel::from_entry(
|
||||
wheel,
|
||||
revision.hashes().into(),
|
||||
CacheInfo::default(),
|
||||
);
|
||||
entries.push(IndexEntry {
|
||||
dist: wheel.into_registry_dist(),
|
||||
index,
|
||||
|
|
|
|||
Loading…
Reference in New Issue