diff --git a/crates/uv-distribution-filename/src/wheel.rs b/crates/uv-distribution-filename/src/wheel.rs index 59a65d4c7..73b906a71 100644 --- a/crates/uv-distribution-filename/src/wheel.rs +++ b/crates/uv-distribution-filename/src/wheel.rs @@ -61,8 +61,8 @@ impl Display for WheelFilename { "{}-{}-{}-{}.whl", self.name.as_dist_info_name(), self.version, - self.tags - variant, + self.tags, + variant ) } else { write!( @@ -364,8 +364,8 @@ impl WheelFilename { Ok(Self { name, version, - variant, tags, + variant, }) } } diff --git a/crates/uv-distribution-types/src/dist_or_variant_filename.rs b/crates/uv-distribution-types/src/dist_or_variant_filename.rs new file mode 100644 index 000000000..bb8c4f536 --- /dev/null +++ b/crates/uv-distribution-types/src/dist_or_variant_filename.rs @@ -0,0 +1,9 @@ +use crate::VariantJson; +use uv_distribution_filename::DistFilename; + +/// On an index page, there can be wheels, source distributions and `variant.json` files. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum DistOrVariantFilename { + DistFilename(DistFilename), + VariantJson(VariantJson), +} diff --git a/crates/uv-distribution-types/src/lib.rs b/crates/uv-distribution-types/src/lib.rs index 1e3ad7eba..66f67d39a 100644 --- a/crates/uv-distribution-types/src/lib.rs +++ b/crates/uv-distribution-types/src/lib.rs @@ -59,6 +59,7 @@ pub use crate::cached::*; pub use crate::dependency_metadata::*; pub use crate::diagnostic::*; pub use crate::dist_error::*; +pub use crate::dist_or_variant_filename::*; pub use crate::error::*; pub use crate::file::*; pub use crate::hash::*; @@ -79,6 +80,7 @@ pub use crate::resolved::*; pub use crate::specified_requirement::*; pub use crate::status_code_strategy::*; pub use crate::traits::*; +pub use crate::variant_json::*; mod annotation; mod any; @@ -87,6 +89,7 @@ mod cached; mod dependency_metadata; mod diagnostic; mod dist_error; +mod dist_or_variant_filename; mod error; mod file; mod hash; @@ -107,6 +110,7 @@ mod resolved; mod specified_requirement; mod status_code_strategy; mod traits; +mod variant_json; #[derive(Debug, Clone)] pub enum VersionOrUrlRef<'a, T: Pep508Url = VerbatimUrl> { diff --git a/crates/uv-distribution-types/src/prioritized_distribution.rs b/crates/uv-distribution-types/src/prioritized_distribution.rs index 70b7129f5..847140b22 100644 --- a/crates/uv-distribution-types/src/prioritized_distribution.rs +++ b/crates/uv-distribution-types/src/prioritized_distribution.rs @@ -13,7 +13,7 @@ use uv_variants::VariantPriority; use crate::{ File, InstalledDist, KnownPlatform, RegistryBuiltDist, RegistryBuiltWheel, RegistrySourceDist, - ResolvedDistRef, + ResolvedDistRef, VariantJson, }; /// A collection of distributions that have been filtered by relevance. @@ -30,6 +30,8 @@ struct PrioritizedDistInner { best_wheel_index: Option, /// The set of all wheels associated with this distribution. wheels: Vec<(RegistryBuiltWheel, WheelCompatibility)>, + /// The `variants.json` file associated with the package version. + variants_json: Option, /// The hashes for each distribution. hashes: Vec, /// The set of supported platforms for the distribution, described in terms of their markers. @@ -42,6 +44,7 @@ impl Default for PrioritizedDistInner { source: None, best_wheel_index: None, wheels: Vec::new(), + variants_json: None, hashes: Vec::new(), markers: MarkerTree::FALSE, } @@ -350,6 +353,7 @@ impl PrioritizedDist { markers: implied_markers(&dist.filename), best_wheel_index: Some(0), wheels: vec![(dist, compatibility)], + variants_json: None, source: None, hashes, })) @@ -366,10 +370,23 @@ impl PrioritizedDist { best_wheel_index: None, wheels: vec![], source: Some((dist, compatibility)), + variants_json: None, hashes, })) } + /// Create a new [`PrioritizedDist`] from the `variant.json`. + pub fn from_variant_json(variant_json: VariantJson) -> Self { + Self(Box::new(PrioritizedDistInner { + markers: MarkerTree::TRUE, + best_wheel_index: None, + wheels: vec![], + source: None, + variants_json: Some(variant_json), + hashes: vec![], + })) + } + /// Insert the given built distribution into the [`PrioritizedDist`]. pub fn insert_built( &mut self, @@ -423,6 +440,14 @@ impl PrioritizedDist { } } + pub fn insert_variant_json(&mut self, variant_json: VariantJson) { + debug_assert!( + self.0.variants_json.is_none(), + "The variant.json filename is unique" + ); + self.0.variants_json = Some(variant_json); + } + /// Return the highest-priority distribution for the package version, if any. pub fn get(&self) -> Option { let best_wheel = self.0.best_wheel_index.map(|i| &self.0.wheels[i]); diff --git a/crates/uv-distribution-types/src/variant_json.rs b/crates/uv-distribution-types/src/variant_json.rs new file mode 100644 index 000000000..cf2d2ae56 --- /dev/null +++ b/crates/uv-distribution-types/src/variant_json.rs @@ -0,0 +1,11 @@ +use crate::FileLocation; +use uv_normalize::PackageName; +use uv_pep440::Version; + +/// A `--variant.json` file. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct VariantJson { + pub name: PackageName, + pub version: Version, + pub file_location: FileLocation, +} diff --git a/crates/uv-resolver/src/flat_index.rs b/crates/uv-resolver/src/flat_index.rs index 6f79bf8b0..1d3b1b454 100644 --- a/crates/uv-resolver/src/flat_index.rs +++ b/crates/uv-resolver/src/flat_index.rs @@ -8,8 +8,8 @@ use uv_client::{FlatIndexEntries, FlatIndexEntry}; use uv_configuration::BuildOptions; use uv_distribution_filename::{DistFilename, SourceDistFilename, WheelFilename}; use uv_distribution_types::{ - File, HashComparison, HashPolicy, IncompatibleSource, IncompatibleWheel, IndexUrl, - PrioritizedDist, RegistryBuiltWheel, RegistrySourceDist, SourceDistCompatibility, + DistOrVariantFilename, File, HashComparison, HashPolicy, IncompatibleSource, IncompatibleWheel, + IndexUrl, PrioritizedDist, RegistryBuiltWheel, RegistrySourceDist, SourceDistCompatibility, WheelCompatibility, }; use uv_normalize::PackageName; @@ -46,7 +46,7 @@ impl FlatIndex { let distributions = index.entry(entry.filename.name().clone()).or_default(); distributions.add_file( entry.file, - entry.filename, + DistOrVariantFilename::DistFilename(entry.filename), tags, variants, hasher, @@ -92,7 +92,7 @@ impl FlatDistributions { for entry in entries { distributions.add_file( entry.file, - entry.filename, + DistOrVariantFilename::DistFilename(entry.filename), tags, variants, hasher, @@ -117,7 +117,7 @@ impl FlatDistributions { fn add_file( &mut self, file: File, - filename: DistFilename, + filename: DistOrVariantFilename, tags: Option<&Tags>, variants: Option<&VariantSet>, hasher: &HashStrategy, @@ -127,7 +127,7 @@ impl FlatDistributions { // No `requires-python` here: for source distributions, we don't have that information; // for wheels, we read it lazily only when selected. match filename { - DistFilename::WheelFilename(filename) => { + DistOrVariantFilename::DistFilename(DistFilename::WheelFilename(filename)) => { let version = filename.version.clone(); let compatibility = Self::wheel_compatibility( @@ -152,7 +152,7 @@ impl FlatDistributions { } } } - DistFilename::SourceDistFilename(filename) => { + DistOrVariantFilename::DistFilename(DistFilename::SourceDistFilename(filename)) => { let compatibility = Self::source_dist_compatibility( &filename, file.hashes.as_slice(), @@ -176,6 +176,16 @@ impl FlatDistributions { } } } + DistOrVariantFilename::VariantJson(variant_json) => { + match self.0.entry(variant_json.version.clone()) { + Entry::Occupied(mut entry) => { + entry.get_mut().insert_variant_json(variant_json); + } + Entry::Vacant(entry) => { + entry.insert(PrioritizedDist::from_variant_json(variant_json)); + } + } + } } }