diff --git a/crates/uv-auth/src/policy.rs b/crates/uv-auth/src/policy.rs index c2d5b4d79..f9077b51c 100644 --- a/crates/uv-auth/src/policy.rs +++ b/crates/uv-auth/src/policy.rs @@ -3,7 +3,17 @@ use url::Url; /// When to use authentication. #[derive( - Copy, Clone, Debug, Default, Hash, Eq, PartialEq, serde::Serialize, serde::Deserialize, + Copy, + Clone, + Debug, + Default, + Hash, + Eq, + PartialEq, + Ord, + PartialOrd, + serde::Serialize, + serde::Deserialize, )] #[serde(rename_all = "kebab-case")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] diff --git a/crates/uv-client/src/registry_client.rs b/crates/uv-client/src/registry_client.rs index 2cf629889..f2d4b1f14 100644 --- a/crates/uv-client/src/registry_client.rs +++ b/crates/uv-client/src/registry_client.rs @@ -13,14 +13,14 @@ use reqwest_middleware::ClientWithMiddleware; use tokio::sync::Semaphore; use tracing::{info_span, instrument, trace, warn, Instrument}; use url::Url; -use uv_auth::UrlAuthPolicies; +use uv_auth::UrlAuthPolicies; use uv_cache::{Cache, CacheBucket, CacheEntry, WheelCache}; use uv_configuration::KeyringProviderType; use uv_configuration::{IndexStrategy, TrustedHost}; use uv_distribution_filename::{DistFilename, SourceDistFilename, WheelFilename}; use uv_distribution_types::{ - BuiltDist, File, FileLocation, Index, IndexCapabilities, IndexUrl, IndexUrls, Name, + BuiltDist, File, FileLocation, IndexCapabilities, IndexMetadataRef, IndexUrl, IndexUrls, Name, }; use uv_metadata::{read_metadata_async_seek, read_metadata_async_stream}; use uv_normalize::PackageName; @@ -255,16 +255,17 @@ impl RegistryClient { } /// Return the appropriate index URLs for the given [`PackageName`]. - fn index_urls_for(&self, package_name: &PackageName) -> impl Iterator { + fn index_urls_for(&self, package_name: &PackageName) -> impl Iterator { self.torch_backend .as_ref() .and_then(|torch_backend| { torch_backend .applies_to(package_name) .then(|| torch_backend.index_urls()) + .map(|indexes| indexes.map(IndexMetadataRef::from)) }) .map(Either::Left) - .unwrap_or_else(|| Either::Right(self.index_urls.indexes().map(Index::url))) + .unwrap_or_else(|| Either::Right(self.index_urls.indexes().map(IndexMetadataRef::from))) } /// Return the appropriate [`IndexStrategy`] for the given [`PackageName`]. @@ -288,10 +289,10 @@ impl RegistryClient { pub async fn simple<'index>( &'index self, package_name: &PackageName, - index: Option<&'index IndexUrl>, + index: Option>, capabilities: &IndexCapabilities, download_concurrency: &Semaphore, - ) -> Result)>, Error> { + ) -> Result, OwnedArchive)>, Error> { // If `--no-index` is specified, avoid fetching regardless of whether the index is implicit, // explicit, etc. if self.index_urls.no_index() { @@ -312,7 +313,7 @@ impl RegistryClient { for index in indexes { let _permit = download_concurrency.acquire().await; if let Some(metadata) = self - .simple_single_index(package_name, index, capabilities) + .simple_single_index(package_name, index.url(), capabilities) .await? { results.push((index, metadata)); @@ -327,7 +328,7 @@ impl RegistryClient { .map(|index| async move { let _permit = download_concurrency.acquire().await; let metadata = self - .simple_single_index(package_name, index, capabilities) + .simple_single_index(package_name, index.url(), capabilities) .await?; Ok((index, metadata)) }) @@ -369,9 +370,9 @@ impl RegistryClient { capabilities: &IndexCapabilities, ) -> Result>, Error> { // Format the URL for PyPI. - let mut url: Url = index.clone().into(); + let mut url = index.url().clone(); url.path_segments_mut() - .map_err(|()| ErrorKind::CannotBeABase(index.clone().into()))? + .map_err(|()| ErrorKind::CannotBeABase(index.url().clone()))? .pop_if_empty() .push(package_name.as_ref()) // The URL *must* end in a trailing slash for proper relative path behavior diff --git a/crates/uv-distribution-types/src/index.rs b/crates/uv-distribution-types/src/index.rs index 256737056..7f5468b4c 100644 --- a/crates/uv-distribution-types/src/index.rs +++ b/crates/uv-distribution-types/src/index.rs @@ -10,7 +10,9 @@ use crate::index_name::{IndexName, IndexNameError}; use crate::origin::Origin; use crate::{IndexUrl, IndexUrlError}; -#[derive(Debug, Clone, Hash, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +#[derive( + Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, serde::Serialize, serde::Deserialize, +)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[serde(rename_all = "kebab-case")] pub struct Index { @@ -200,6 +202,20 @@ impl Index { } } +impl From for Index { + fn from(value: IndexUrl) -> Self { + Self { + name: None, + url: value, + explicit: false, + default: false, + origin: None, + publish_url: None, + authenticate: AuthPolicy::default(), + } + } +} + impl FromStr for Index { type Err = IndexSourceError; @@ -235,6 +251,76 @@ impl FromStr for Index { } } +/// An [`IndexUrl`] along with the metadata necessary to query the index. +#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] +pub struct IndexMetadata { + pub url: IndexUrl, + // /// The type of the index. + // /// + // /// Indexes can either be PEP 503-compliant (i.e., a registry implementing the Simple API) or + // /// structured as a flat list of distributions (e.g., `--find-links`). In both cases, indexes + // /// can point to either local or remote resources. + // #[serde(default)] + // pub r#type: IndexKind, +} + +impl IndexMetadata { + /// Return a reference to the [`IndexMetadata`]. + pub fn as_ref(&self) -> IndexMetadataRef<'_> { + let Self { url } = self; + IndexMetadataRef { url } + } + + /// Consume the [`IndexMetadata`] and return the [`IndexUrl`]. + pub fn into_url(self) -> IndexUrl { + self.url + } +} + +/// A reference to an [`IndexMetadata`]. +#[derive(Debug, Copy, Clone)] +pub struct IndexMetadataRef<'a> { + pub url: &'a IndexUrl, +} + +impl IndexMetadata { + /// Return the [`IndexUrl`] of the index. + pub fn url(&self) -> &IndexUrl { + &self.url + } +} + +impl IndexMetadataRef<'_> { + /// Return the [`IndexUrl`] of the index. + pub fn url(&self) -> &IndexUrl { + self.url + } +} + +impl<'a> From<&'a IndexMetadata> for IndexMetadataRef<'a> { + fn from(value: &'a IndexMetadata) -> Self { + Self { url: &value.url } + } +} + +impl<'a> From<&'a IndexUrl> for IndexMetadataRef<'a> { + fn from(value: &'a IndexUrl) -> Self { + Self { url: value } + } +} + +impl<'a> From<&'a Index> for IndexMetadataRef<'a> { + fn from(value: &'a Index) -> Self { + Self { url: &value.url } + } +} + +impl From for IndexMetadata { + fn from(value: IndexUrl) -> Self { + Self { url: value } + } +} + /// An error that can occur when parsing an [`Index`]. #[derive(Error, Debug)] pub enum IndexSourceError { diff --git a/crates/uv-distribution-types/src/index_name.rs b/crates/uv-distribution-types/src/index_name.rs index ebc91d2f7..02acbf09b 100644 --- a/crates/uv-distribution-types/src/index_name.rs +++ b/crates/uv-distribution-types/src/index_name.rs @@ -9,7 +9,7 @@ use uv_small_str::SmallString; /// The normalized name of an index. /// /// Index names may contain letters, digits, hyphens, underscores, and periods, and must be ASCII. -#[derive(Debug, Clone, Hash, Eq, PartialEq, serde::Serialize)] +#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, serde::Serialize)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct IndexName(SmallString); diff --git a/crates/uv-distribution-types/src/origin.rs b/crates/uv-distribution-types/src/origin.rs index 286735545..f5f3cd7cb 100644 --- a/crates/uv-distribution-types/src/origin.rs +++ b/crates/uv-distribution-types/src/origin.rs @@ -1,5 +1,5 @@ /// The origin of a piece of configuration. -#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] pub enum Origin { /// The setting was provided via the CLI. Cli, diff --git a/crates/uv-distribution-types/src/requirement.rs b/crates/uv-distribution-types/src/requirement.rs index 28bc0ea48..751f7d6eb 100644 --- a/crates/uv-distribution-types/src/requirement.rs +++ b/crates/uv-distribution-types/src/requirement.rs @@ -14,6 +14,9 @@ use uv_pep440::VersionSpecifiers; use uv_pep508::{ marker, MarkerEnvironment, MarkerTree, RequirementOrigin, VerbatimUrl, VersionOrUrl, }; + +use crate::{IndexMetadata, IndexUrl}; + use uv_pypi_types::{ ConflictItem, Hashes, ParsedArchiveUrl, ParsedDirectoryUrl, ParsedGitUrl, ParsedPathUrl, ParsedUrl, ParsedUrlError, VerbatimParsedUrl, @@ -320,7 +323,7 @@ impl Display for Requirement { } => { write!(f, "{specifier}")?; if let Some(index) = index { - write!(f, " (index: {index})")?; + write!(f, " (index: {})", index.url)?; } } RequirementSource::Url { url, .. } => { @@ -368,7 +371,7 @@ pub enum RequirementSource { Registry { specifier: VersionSpecifiers, /// Choose a version from the index at the given URL. - index: Option, + index: Option, /// The conflict item associated with the source, if any. conflict: Option, }, @@ -600,7 +603,7 @@ impl Display for RequirementSource { } => { write!(f, "{specifier}")?; if let Some(index) = index { - write!(f, " (index: {index})")?; + write!(f, " (index: {})", index.url)?; } } Self::Url { url, .. } => { @@ -662,12 +665,13 @@ impl From for RequirementSourceWire { match value { RequirementSource::Registry { specifier, - mut index, + index, conflict, } => { - if let Some(index) = index.as_mut() { - redact_credentials(index); - } + let index = index.map(|index| index.url.into_url()).map(|mut index| { + redact_credentials(&mut index); + index + }); Self::Registry { specifier, index, @@ -775,7 +779,8 @@ impl TryFrom for RequirementSource { conflict, } => Ok(Self::Registry { specifier, - index, + index: index + .map(|index| IndexMetadata::from(IndexUrl::from(VerbatimUrl::from_url(index)))), conflict, }), RequirementSourceWire::Git { git } => { diff --git a/crates/uv-distribution-types/src/resolution.rs b/crates/uv-distribution-types/src/resolution.rs index efbfb616f..ea02c64f4 100644 --- a/crates/uv-distribution-types/src/resolution.rs +++ b/crates/uv-distribution-types/src/resolution.rs @@ -3,7 +3,9 @@ use uv_normalize::{ExtraName, GroupName, PackageName}; use uv_pep508::MarkerTree; use uv_pypi_types::{HashDigest, HashDigests}; -use crate::{BuiltDist, Diagnostic, Dist, Name, RequirementSource, ResolvedDist, SourceDist}; +use crate::{ + BuiltDist, Diagnostic, Dist, IndexMetadata, Name, RequirementSource, ResolvedDist, SourceDist, +}; /// A set of packages pinned at specific versions. /// @@ -229,7 +231,7 @@ impl From<&ResolvedDist> for RequirementSource { wheel.filename.version.clone(), ), ), - index: Some(wheel.index.url().clone()), + index: Some(IndexMetadata::from(wheel.index.clone())), conflict: None, } } @@ -252,7 +254,7 @@ impl From<&ResolvedDist> for RequirementSource { specifier: uv_pep440::VersionSpecifiers::from( uv_pep440::VersionSpecifier::equals_version(sdist.version.clone()), ), - index: Some(sdist.index.url().clone()), + index: Some(IndexMetadata::from(sdist.index.clone())), conflict: None, }, Dist::Source(SourceDist::DirectUrl(sdist)) => { diff --git a/crates/uv-distribution/src/metadata/lowering.rs b/crates/uv-distribution/src/metadata/lowering.rs index 323889229..a7856c40d 100644 --- a/crates/uv-distribution/src/metadata/lowering.rs +++ b/crates/uv-distribution/src/metadata/lowering.rs @@ -8,7 +8,7 @@ use url::Url; use uv_distribution_filename::DistExtension; use uv_distribution_types::{ - Index, IndexLocations, IndexName, Origin, Requirement, RequirementSource, + Index, IndexLocations, IndexMetadata, IndexName, Origin, Requirement, RequirementSource, }; use uv_git_types::{GitReference, GitUrl, GitUrlParseError}; use uv_normalize::{ExtraName, GroupName, PackageName}; @@ -222,7 +222,9 @@ impl LoweredRequirement { .find(|Index { name, .. }| { name.as_ref().is_some_and(|name| *name == index) }) - .map(|Index { url: index, .. }| index.clone()) + .map(|index| IndexMetadata { + url: index.url.clone(), + }) else { return Err(LoweringError::MissingIndex( requirement.name.clone(), @@ -238,7 +240,7 @@ impl LoweredRequirement { }) } }); - let source = registry_source(&requirement, index.into_url(), conflict); + let source = registry_source(&requirement, index, conflict); (source, marker) } Source::Workspace { @@ -445,7 +447,9 @@ impl LoweredRequirement { .find(|Index { name, .. }| { name.as_ref().is_some_and(|name| *name == index) }) - .map(|Index { url: index, .. }| index.clone()) + .map(|index| IndexMetadata { + url: index.url.clone(), + }) else { return Err(LoweringError::MissingIndex( requirement.name.clone(), @@ -453,7 +457,7 @@ impl LoweredRequirement { )); }; let conflict = None; - let source = registry_source(&requirement, index.into_url(), conflict); + let source = registry_source(&requirement, index, conflict); (source, marker) } Source::Workspace { .. } => { @@ -627,7 +631,7 @@ fn url_source( /// Convert a registry source into a [`RequirementSource`]. fn registry_source( requirement: &uv_pep508::Requirement, - index: Url, + index: IndexMetadata, conflict: Option, ) -> RequirementSource { match &requirement.version_or_url { diff --git a/crates/uv-publish/src/lib.rs b/crates/uv-publish/src/lib.rs index db0290953..fdb9429ff 100644 --- a/crates/uv-publish/src/lib.rs +++ b/crates/uv-publish/src/lib.rs @@ -479,7 +479,7 @@ pub async fn check_url( let response = match registry_client .simple( filename.name(), - Some(index_url), + Some(index_url.into()), index_capabilities, download_concurrency, ) diff --git a/crates/uv-resolver/src/fork_indexes.rs b/crates/uv-resolver/src/fork_indexes.rs index e575dfc8b..bb2045bab 100644 --- a/crates/uv-resolver/src/fork_indexes.rs +++ b/crates/uv-resolver/src/fork_indexes.rs @@ -1,5 +1,5 @@ use rustc_hash::FxHashMap; -use uv_distribution_types::IndexUrl; +use uv_distribution_types::IndexMetadata; use uv_normalize::PackageName; use crate::resolver::ResolverEnvironment; @@ -7,24 +7,24 @@ use crate::ResolveError; /// See [`crate::resolver::ForkState`]. #[derive(Default, Debug, Clone)] -pub(crate) struct ForkIndexes(FxHashMap); +pub(crate) struct ForkIndexes(FxHashMap); impl ForkIndexes { - /// Get the [`IndexUrl`] previously used for a package in this fork. - pub(crate) fn get(&self, package_name: &PackageName) -> Option<&IndexUrl> { + /// Get the [`Index`] previously used for a package in this fork. + pub(crate) fn get(&self, package_name: &PackageName) -> Option<&IndexMetadata> { self.0.get(package_name) } - /// Check that this is the only [`IndexUrl`] used for this package in this fork. + /// Check that this is the only [`Index`] used for this package in this fork. pub(crate) fn insert( &mut self, package_name: &PackageName, - index: &IndexUrl, + index: &IndexMetadata, env: &ResolverEnvironment, ) -> Result<(), ResolveError> { if let Some(previous) = self.0.insert(package_name.clone(), index.clone()) { if &previous != index { - let mut conflicts = vec![previous.to_string(), index.to_string()]; + let mut conflicts = vec![previous.url.to_string(), index.url.to_string()]; conflicts.sort(); return Err(ResolveError::ConflictingIndexesForEnvironment { package_name: package_name.clone(), diff --git a/crates/uv-resolver/src/lock/mod.rs b/crates/uv-resolver/src/lock/mod.rs index 4fe07c00e..3b1d0582b 100644 --- a/crates/uv-resolver/src/lock/mod.rs +++ b/crates/uv-resolver/src/lock/mod.rs @@ -27,9 +27,9 @@ use uv_distribution_filename::{ use uv_distribution_types::{ redact_credentials, BuiltDist, DependencyMetadata, DirectUrlBuiltDist, DirectUrlSourceDist, DirectorySourceDist, Dist, DistributionMetadata, FileLocation, GitSourceDist, IndexLocations, - IndexUrl, Name, PathBuiltDist, PathSourceDist, RegistryBuiltDist, RegistryBuiltWheel, - RegistrySourceDist, RemoteSource, Requirement, RequirementSource, ResolvedDist, StaticMetadata, - ToUrlError, UrlString, + IndexMetadata, IndexUrl, Name, PathBuiltDist, PathSourceDist, RegistryBuiltDist, + RegistryBuiltWheel, RegistrySourceDist, RemoteSource, Requirement, RequirementSource, + ResolvedDist, StaticMetadata, ToUrlError, UrlString, }; use uv_fs::{relative_to, PortablePath, PortablePathBuf}; use uv_git::{RepositoryReference, ResolvedRepositoryReference}; @@ -4563,12 +4563,17 @@ fn normalize_requirement( } RequirementSource::Registry { specifier, - mut index, + index, conflict, } => { - if let Some(index) = index.as_mut() { - redact_credentials(index); - } + // Round-trip the index to remove anything apart from the URL. + let index = index + .map(|index| index.url.into_url()) + .map(|mut index| { + redact_credentials(&mut index); + index + }) + .map(|index| IndexMetadata::from(IndexUrl::from(VerbatimUrl::from_url(index)))); Ok(Requirement { name: requirement.name, extras: requirement.extras, diff --git a/crates/uv-resolver/src/pubgrub/report.rs b/crates/uv-resolver/src/pubgrub/report.rs index f4a07b40d..4fe68fbf0 100644 --- a/crates/uv-resolver/src/pubgrub/report.rs +++ b/crates/uv-resolver/src/pubgrub/report.rs @@ -11,7 +11,7 @@ use rustc_hash::FxHashMap; use uv_configuration::{IndexStrategy, NoBinary, NoBuild}; use uv_distribution_types::{ IncompatibleDist, IncompatibleSource, IncompatibleWheel, Index, IndexCapabilities, - IndexLocations, IndexUrl, + IndexLocations, IndexMetadata, IndexUrl, }; use uv_normalize::PackageName; use uv_pep440::{Version, VersionSpecifiers}; @@ -727,7 +727,7 @@ impl PubGrubReportFormatter<'_> { env: &ResolverEnvironment, tags: Option<&Tags>, ) -> Option { - let response = if let Some(url) = fork_indexes.get(name) { + let response = if let Some(url) = fork_indexes.get(name).map(IndexMetadata::url) { index.explicit().get(&(name.clone(), url.clone())) } else { index.implicit().get(name) diff --git a/crates/uv-resolver/src/resolver/batch_prefetch.rs b/crates/uv-resolver/src/resolver/batch_prefetch.rs index 6d35a2f97..104d080e1 100644 --- a/crates/uv-resolver/src/resolver/batch_prefetch.rs +++ b/crates/uv-resolver/src/resolver/batch_prefetch.rs @@ -13,7 +13,9 @@ use crate::resolver::Request; use crate::{ InMemoryIndex, PythonRequirement, ResolveError, ResolverEnvironment, VersionsResponse, }; -use uv_distribution_types::{CompatibleDist, DistributionMetadata, IndexCapabilities, IndexUrl}; +use uv_distribution_types::{ + CompatibleDist, DistributionMetadata, IndexCapabilities, IndexMetadata, +}; use uv_normalize::PackageName; use uv_pep440::Version; use uv_pep508::MarkerTree; @@ -81,7 +83,7 @@ impl BatchPrefetcher { pub(crate) fn prefetch_batches( &mut self, next: &PubGrubPackage, - index: Option<&IndexUrl>, + index: Option<&IndexMetadata>, version: &Version, current_range: &Range, unchangeable_constraints: Option<&Term>>, @@ -110,7 +112,7 @@ impl BatchPrefetcher { self.prefetch_runner .index .explicit() - .wait_blocking(&(name.clone(), index.clone())) + .wait_blocking(&(name.clone(), index.url().clone())) .ok_or_else(|| ResolveError::UnregisteredTask(name.to_string()))? } else { self.prefetch_runner diff --git a/crates/uv-resolver/src/resolver/indexes.rs b/crates/uv-resolver/src/resolver/indexes.rs index ae4915b04..8a5b2a8af 100644 --- a/crates/uv-resolver/src/resolver/indexes.rs +++ b/crates/uv-resolver/src/resolver/indexes.rs @@ -1,6 +1,5 @@ -use uv_distribution_types::{IndexUrl, RequirementSource}; +use uv_distribution_types::{IndexMetadata, RequirementSource}; use uv_normalize::PackageName; -use uv_pep508::VerbatimUrl; use uv_pypi_types::ConflictItem; use crate::resolver::ForkMap; @@ -24,7 +23,7 @@ pub(crate) struct Indexes(ForkMap); #[derive(Debug, Clone)] struct Entry { - index: IndexUrl, + index: IndexMetadata, conflict: Option, } @@ -46,7 +45,9 @@ impl Indexes { else { continue; }; - let index = IndexUrl::from(VerbatimUrl::from_url(index.clone())); + let index = IndexMetadata { + url: index.url.clone(), + }; let conflict = conflict.clone(); indexes.add(&requirement, Entry { index, conflict }); } @@ -60,7 +61,7 @@ impl Indexes { } /// Return the explicit index used for a package in the given fork. - pub(crate) fn get(&self, name: &PackageName, env: &ResolverEnvironment) -> Vec<&IndexUrl> { + pub(crate) fn get(&self, name: &PackageName, env: &ResolverEnvironment) -> Vec<&IndexMetadata> { let entries = self.0.get(name, env); entries .iter() diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index 9a7bf38ee..e291297b1 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -25,8 +25,8 @@ use uv_distribution::DistributionDatabase; use uv_distribution_types::{ BuiltDist, CompatibleDist, DerivationChain, Dist, DistErrorKind, DistributionMetadata, IncompatibleDist, IncompatibleSource, IncompatibleWheel, IndexCapabilities, IndexLocations, - IndexUrl, InstalledDist, PythonRequirementKind, RemoteSource, Requirement, ResolvedDist, - ResolvedDistRef, SourceDist, VersionOrUrlRef, + IndexMetadata, IndexUrl, InstalledDist, PythonRequirementKind, RemoteSource, Requirement, + ResolvedDist, ResolvedDistRef, SourceDist, VersionOrUrlRef, }; use uv_git::GitResolver; use uv_normalize::{ExtraName, GroupName, PackageName}; @@ -494,7 +494,7 @@ impl ResolverState ResolverState, - index: Option<&IndexUrl>, + index: Option<&IndexMetadata>, request_sink: &Sender, ) -> Result<(), ResolveError> { // Ignore unresolved URL packages, i.e., packages that use a direct URL in some forks. @@ -945,7 +945,7 @@ impl ResolverState, - index: Option<&IndexUrl>, + index: Option<&IndexMetadata>, request_sink: &Sender, ) -> Result<(), ResolveError> { // Only request real packages. @@ -969,7 +969,7 @@ impl ResolverState ResolverState ResolverState), + Package(PackageName, Option), /// A request to fetch the metadata for a built or source distribution. Dist(Dist), /// A request to fetch the metadata from an already-installed distribution. diff --git a/crates/uv-resolver/src/resolver/provider.rs b/crates/uv-resolver/src/resolver/provider.rs index 2378afc5b..bf19f690b 100644 --- a/crates/uv-resolver/src/resolver/provider.rs +++ b/crates/uv-resolver/src/resolver/provider.rs @@ -3,7 +3,9 @@ use std::sync::Arc; use uv_configuration::BuildOptions; use uv_distribution::{ArchiveMetadata, DistributionDatabase, Reporter}; -use uv_distribution_types::{Dist, IndexCapabilities, IndexUrl, InstalledDist, RequestedDist}; +use uv_distribution_types::{ + Dist, IndexCapabilities, IndexMetadata, IndexMetadataRef, InstalledDist, RequestedDist, +}; use uv_normalize::PackageName; use uv_pep440::{Version, VersionSpecifiers}; use uv_platform_tags::Tags; @@ -78,7 +80,7 @@ pub trait ResolverProvider { fn get_package_versions<'io>( &'io self, package_name: &'io PackageName, - index: Option<&'io IndexUrl>, + index: Option<&'io IndexMetadata>, ) -> impl Future + 'io; /// Get the metadata for a distribution. @@ -150,13 +152,18 @@ impl ResolverProvider for DefaultResolverProvider<'_, Con async fn get_package_versions<'io>( &'io self, package_name: &'io PackageName, - index: Option<&'io IndexUrl>, + index: Option<&'io IndexMetadata>, ) -> PackageVersionsResult { let result = self .fetcher .client() .manual(|client, semaphore| { - client.simple(package_name, index, self.capabilities, semaphore) + client.simple( + package_name, + index.map(IndexMetadataRef::from), + self.capabilities, + semaphore, + ) }) .await; @@ -171,7 +178,7 @@ impl ResolverProvider for DefaultResolverProvider<'_, Con VersionMap::from_metadata( metadata, package_name, - index, + index.url(), self.tags.as_ref(), &self.requires_python, &self.allowed_yanks, diff --git a/crates/uv/src/commands/pip/latest.rs b/crates/uv/src/commands/pip/latest.rs index 12f563629..7c6eee834 100644 --- a/crates/uv/src/commands/pip/latest.rs +++ b/crates/uv/src/commands/pip/latest.rs @@ -2,7 +2,7 @@ use tokio::sync::Semaphore; use tracing::debug; use uv_client::{RegistryClient, VersionFiles}; use uv_distribution_filename::DistFilename; -use uv_distribution_types::{IndexCapabilities, IndexUrl}; +use uv_distribution_types::{IndexCapabilities, IndexMetadataRef, IndexUrl}; use uv_normalize::PackageName; use uv_platform_tags::Tags; use uv_resolver::{ExcludeNewer, PrereleaseMode, RequiresPython}; @@ -34,7 +34,12 @@ impl LatestClient<'_> { let archives = match self .client - .simple(package, index, self.capabilities, download_concurrency) + .simple( + package, + index.map(IndexMetadataRef::from), + self.capabilities, + download_concurrency, + ) .await { Ok(archives) => archives, diff --git a/crates/uv/src/commands/publish.rs b/crates/uv/src/commands/publish.rs index 3aed01770..16568373f 100644 --- a/crates/uv/src/commands/publish.rs +++ b/crates/uv/src/commands/publish.rs @@ -1,17 +1,15 @@ -use crate::commands::reporters::PublishReporter; -use crate::commands::{human_readable_bytes, ExitStatus}; -use crate::printer::Printer; -use crate::settings::NetworkSettings; -use anyhow::{bail, Context, Result}; -use console::Term; -use owo_colors::OwoColorize; use std::fmt::Write; use std::iter; use std::sync::Arc; use std::time::Duration; + +use anyhow::{bail, Context, Result}; +use console::Term; +use owo_colors::OwoColorize; use tokio::sync::Semaphore; use tracing::{debug, info}; use url::Url; + use uv_cache::Cache; use uv_client::{AuthIntegration, BaseClient, BaseClientBuilder, RegistryClientBuilder}; use uv_configuration::{KeyringProviderType, TrustedPublishing}; @@ -21,6 +19,11 @@ use uv_publish::{ }; use uv_warnings::warn_user_once; +use crate::commands::reporters::PublishReporter; +use crate::commands::{human_readable_bytes, ExitStatus}; +use crate::printer::Printer; +use crate::settings::NetworkSettings; + pub(crate) async fn publish( paths: Vec, publish_url: Url, diff --git a/crates/uv/tests/it/lock.rs b/crates/uv/tests/it/lock.rs index e1b72e185..1a4c286b8 100644 --- a/crates/uv/tests/it/lock.rs +++ b/crates/uv/tests/it/lock.rs @@ -15331,7 +15331,7 @@ fn lock_explicit_default_index() -> Result<()> { DEBUG No workspace root found, using project root DEBUG Ignoring existing lockfile due to mismatched requirements for: `project==0.1.0` Requested: {Requirement { name: PackageName("anyio"), extras: [], groups: [], marker: true, source: Registry { specifier: VersionSpecifiers([]), index: None, conflict: None }, origin: None }} - Existing: {Requirement { name: PackageName("iniconfig"), extras: [], groups: [], marker: true, source: Registry { specifier: VersionSpecifiers([VersionSpecifier { operator: Equal, version: "2.0.0" }]), index: Some(Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("test.pypi.org")), port: None, path: "/simple", query: None, fragment: None }), conflict: None }, origin: None }} + Existing: {Requirement { name: PackageName("iniconfig"), extras: [], groups: [], marker: true, source: Registry { specifier: VersionSpecifiers([VersionSpecifier { operator: Equal, version: "2.0.0" }]), index: Some(IndexMetadata { url: Url(VerbatimUrl { url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("test.pypi.org")), port: None, path: "/simple", query: None, fragment: None }, given: None }) }), conflict: None }, origin: None }} DEBUG Solving with installed Python version: 3.12.[X] DEBUG Solving with target Python version: >=3.12 DEBUG Adding direct dependency: project*