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_normalize::PackageName;
|
||||||
use uv_platform_tags::Tags;
|
use uv_platform_tags::Tags;
|
||||||
|
use uv_pypi_types::HashDigests;
|
||||||
use uv_types::HashStrategy;
|
use uv_types::HashStrategy;
|
||||||
|
|
||||||
use crate::Error;
|
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};
|
use crate::source::{HTTP_REVISION, HttpRevisionPointer, LOCAL_REVISION, LocalRevisionPointer};
|
||||||
|
|
||||||
/// A local index of built distributions for a specific source distribution.
|
/// 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.
|
/// 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> {
|
pub fn path(&self, source_dist: &PathSourceDist) -> Result<Option<CachedWheel>, Error> {
|
||||||
|
|
@ -141,7 +144,7 @@ impl<'a> BuiltWheelIndex<'a> {
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.find(&cache_shard)
|
.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
|
/// Return the most compatible [`CachedWheel`] for a given source distribution built from a
|
||||||
|
|
@ -199,7 +202,7 @@ impl<'a> BuiltWheelIndex<'a> {
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.find(&cache_shard)
|
.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.
|
/// 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)
|
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.
|
/// 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`.
|
/// The `shard` should be `built-wheels-v0/pypi/django-allauth-0.51.0.tar.gz`.
|
||||||
fn find(&self, shard: &CacheShard) -> Option<CachedWheel> {
|
fn find(&self, shard: &CacheShard) -> Option<ResolvedWheel> {
|
||||||
let mut candidate: Option<CachedWheel> = None;
|
let mut candidate: Option<ResolvedWheel> = None;
|
||||||
|
|
||||||
// Unzipped wheels are stored as symlinks into the archive directory.
|
// Unzipped wheels are stored as symlinks into the archive directory.
|
||||||
for wheel_dir in uv_fs::entries(shard).ok().into_iter().flatten() {
|
for wheel_dir in uv_fs::entries(shard).ok().into_iter().flatten() {
|
||||||
|
|
@ -265,7 +269,7 @@ impl<'a> BuiltWheelIndex<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
match CachedWheel::from_built_source(&wheel_dir, self.cache) {
|
match ResolvedWheel::from_built_source(&wheel_dir, self.cache) {
|
||||||
None => {}
|
None => {}
|
||||||
Some(dist_info) => {
|
Some(dist_info) => {
|
||||||
// Pick the wheel with the highest priority
|
// Pick the wheel with the highest priority
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,30 @@ use uv_pypi_types::{HashDigest, HashDigests, VerbatimParsedUrl};
|
||||||
use crate::archive::Archive;
|
use crate::archive::Archive;
|
||||||
use crate::{HttpArchivePointer, LocalArchivePointer};
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CachedWheel {
|
pub struct CachedWheel {
|
||||||
/// The filename of the wheel.
|
/// The filename of the wheel.
|
||||||
|
|
@ -25,21 +49,62 @@ pub struct CachedWheel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedWheel {
|
impl CachedWheel {
|
||||||
/// Try to parse a distribution from a cached directory name (like `typing-extensions-4.8.0-py3-none-any`).
|
/// Create a [`CachedWheel`] from a [`ResolvedWheel`].
|
||||||
pub fn from_built_source(path: impl AsRef<Path>, cache: &Cache) -> Option<Self> {
|
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();
|
let path = path.as_ref();
|
||||||
|
|
||||||
// Determine the wheel filename.
|
// Read the pointer.
|
||||||
let filename = path.file_name()?.to_str()?;
|
let pointer = HttpArchivePointer::read_from(path).ok()??;
|
||||||
let filename = WheelFilename::from_stem(filename).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.
|
// 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 {
|
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,
|
entry,
|
||||||
hashes,
|
hashes,
|
||||||
cache_info,
|
cache_info,
|
||||||
|
|
@ -115,64 +180,6 @@ impl CachedWheel {
|
||||||
cache_info: self.cache_info,
|
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 {
|
impl Hashed for CachedWheel {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::collections::hash_map::Entry;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use uv_cache::{Cache, CacheBucket, WheelCache};
|
use uv_cache::{Cache, CacheBucket, WheelCache};
|
||||||
|
use uv_cache_info::CacheInfo;
|
||||||
use uv_cache_key::cache_digest;
|
use uv_cache_key::cache_digest;
|
||||||
use uv_distribution_types::{
|
use uv_distribution_types::{
|
||||||
BuildVariables, CachedRegistryDist, ConfigSettings, ExtraBuildRequirement, ExtraBuildRequires,
|
BuildVariables, CachedRegistryDist, ConfigSettings, ExtraBuildRequirement, ExtraBuildRequires,
|
||||||
|
|
@ -14,7 +15,7 @@ use uv_normalize::PackageName;
|
||||||
use uv_platform_tags::Tags;
|
use uv_platform_tags::Tags;
|
||||||
use uv_types::HashStrategy;
|
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};
|
use crate::source::{HTTP_REVISION, HttpRevisionPointer, LOCAL_REVISION, LocalRevisionPointer};
|
||||||
|
|
||||||
/// An entry in the [`RegistryWheelIndex`].
|
/// An entry in the [`RegistryWheelIndex`].
|
||||||
|
|
@ -247,13 +248,18 @@ impl<'a> RegistryWheelIndex<'a> {
|
||||||
continue;
|
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() {
|
if wheel.filename.compatibility(tags).is_compatible() {
|
||||||
// Enforce hash-checking based on the source distribution.
|
// Enforce hash-checking based on the source distribution.
|
||||||
if revision.satisfies(
|
if revision.satisfies(
|
||||||
hasher
|
hasher
|
||||||
.get_package(&wheel.filename.name, &wheel.filename.version),
|
.get_package(&wheel.filename.name, &wheel.filename.version),
|
||||||
) {
|
) {
|
||||||
|
let wheel = CachedWheel::from_entry(
|
||||||
|
wheel,
|
||||||
|
revision.hashes().into(),
|
||||||
|
CacheInfo::default(),
|
||||||
|
);
|
||||||
entries.push(IndexEntry {
|
entries.push(IndexEntry {
|
||||||
dist: wheel.into_registry_dist(),
|
dist: wheel.into_registry_dist(),
|
||||||
index,
|
index,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue