Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/uv-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ uv-configuration = { workspace = true }
uv-distribution-filename = { workspace = true }
uv-distribution-types = { workspace = true }
uv-fs = { workspace = true, features = ["tokio"] }
uv-git = { workspace = true }
uv-metadata = { workspace = true }
uv-normalize = { workspace = true }
uv-pep440 = { workspace = true }
Expand Down
3 changes: 3 additions & 0 deletions crates/uv-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,9 @@ pub enum ErrorKind {
#[error(transparent)]
Flat(#[from] FlatIndexError),

#[error(transparent)]
Git(#[from] uv_git::GitResolverError),

#[error("Expected a file URL, but received: {0}")]
NonFileUrl(DisplaySafeUrl),

Expand Down
34 changes: 34 additions & 0 deletions crates/uv-client/src/registry_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use uv_distribution_types::{
BuiltDist, File, IndexCapabilities, IndexFormat, IndexLocations, IndexMetadataRef,
IndexStatusCodeDecision, IndexStatusCodeStrategy, IndexUrl, IndexUrls, Name,
};
use uv_git::{GitResolver, Reporter};
use uv_metadata::{read_metadata_async_seek, read_metadata_async_stream};
use uv_normalize::PackageName;
use uv_pep440::Version;
Expand Down Expand Up @@ -909,7 +910,9 @@ impl RegistryClient {
pub async fn wheel_metadata(
&self,
built_dist: &BuiltDist,
git: &GitResolver,
capabilities: &IndexCapabilities,
reporter: Option<Arc<dyn Reporter>>,
) -> Result<ResolutionMetadata, Error> {
let metadata = match &built_dist {
BuiltDist::Registry(wheels) => {
Expand Down Expand Up @@ -986,6 +989,37 @@ impl RegistryClient {
)
})?
}
BuiltDist::GitPath(wheel) => {
// Fetch the Git repository.
let fetch = git
.fetch(
&wheel.git,
self.disable_ssl(wheel.git.url()),
self.connectivity() == Connectivity::Offline,
self.cache.bucket(CacheBucket::Git),
reporter,
)
.await
.map_err(ErrorKind::Git)?;

// Read the metadata.
let file = fs_err::tokio::File::open(fetch.path().join(&wheel.install_path))
.await
.map_err(ErrorKind::Io)?;
let reader = tokio::io::BufReader::new(file);
let contents = read_metadata_async_seek(&wheel.filename, reader)
.await
.map_err(|err| {
ErrorKind::Metadata(wheel.install_path.to_string_lossy().to_string(), err)
})?;
ResolutionMetadata::parse_metadata(&contents).map_err(|err| {
ErrorKind::MetadataParseError(
wheel.filename.clone(),
built_dist.to_string(),
Box::new(err),
)
})?
}
};

if metadata.name != *built_dist.name() {
Expand Down
6 changes: 5 additions & 1 deletion crates/uv-client/tests/it/remote_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use uv_cache::Cache;
use uv_client::{BaseClientBuilder, RegistryClientBuilder};
use uv_distribution_filename::WheelFilename;
use uv_distribution_types::{BuiltDist, DirectUrlBuiltDist, IndexCapabilities};
use uv_git::GitResolver;
use uv_pep508::VerbatimUrl;
use uv_redacted::DisplaySafeUrl;

Expand All @@ -24,8 +25,11 @@ async fn remote_metadata_with_and_without_cache() -> Result<()> {
location: Box::new(DisplaySafeUrl::parse(url)?),
url: VerbatimUrl::from_str(url)?,
});
let resolver = GitResolver::default();
let capabilities = IndexCapabilities::default();
let metadata = client.wheel_metadata(&dist, &capabilities).await?;
let metadata = client
.wheel_metadata(&dist, &resolver, &capabilities, None)
.await?;
assert_eq!(metadata.version.to_string(), "4.66.1");
}

Expand Down
1 change: 1 addition & 0 deletions crates/uv-dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ uv-configuration = { workspace = true }
uv-distribution-filename = { workspace = true }
uv-distribution-types = { workspace = true }
uv-extract = { workspace = true }
uv-git = { workspace = true }
uv-installer = { workspace = true }
uv-macros = { workspace = true }
uv-options-metadata = { workspace = true }
Expand Down
4 changes: 4 additions & 0 deletions crates/uv-dev/src/wheel_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use uv_cache::{Cache, CacheArgs};
use uv_client::{BaseClientBuilder, RegistryClientBuilder};
use uv_distribution_filename::WheelFilename;
use uv_distribution_types::{BuiltDist, DirectUrlBuiltDist, IndexCapabilities, RemoteSource};
use uv_git::GitResolver;
use uv_pep508::VerbatimUrl;
use uv_pypi_types::ParsedUrl;
use uv_settings::EnvironmentOptions;
Expand All @@ -31,6 +32,7 @@ pub(crate) async fn wheel_metadata(
cache,
)
.build()?;
let resolver = GitResolver::default();
let capabilities = IndexCapabilities::default();

let filename = WheelFilename::from_str(&args.url.filename()?)?;
Expand All @@ -46,7 +48,9 @@ pub(crate) async fn wheel_metadata(
location: Box::new(archive.url),
url: args.url,
}),
&resolver,
&capabilities,
None,
)
.await?;
println!("{metadata:?}");
Expand Down
8 changes: 4 additions & 4 deletions crates/uv-distribution-types/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::{InstalledMetadata, InstalledVersion, Name};
/// kind.
#[derive(Debug, Clone, Eq)]
pub enum LocalDist {
Cached(CachedDist, CanonicalVersion),
Installed(InstalledDist, CanonicalVersion),
Cached(Box<CachedDist>, CanonicalVersion),
Installed(Box<InstalledDist>, CanonicalVersion),
}

impl LocalDist {
Expand Down Expand Up @@ -48,14 +48,14 @@ impl InstalledMetadata for LocalDist {
impl From<CachedDist> for LocalDist {
fn from(dist: CachedDist) -> Self {
let version = CanonicalVersion::from(dist.installed_version());
Self::Cached(dist, version)
Self::Cached(Box::new(dist), version)
}
}

impl From<InstalledDist> for LocalDist {
fn from(dist: InstalledDist) -> Self {
let version = CanonicalVersion::from(dist.installed_version());
Self::Installed(dist, version)
Self::Installed(Box::new(dist), version)
}
}

Expand Down
48 changes: 40 additions & 8 deletions crates/uv-distribution-types/src/buildable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use uv_pep508::VerbatimUrl;
use uv_normalize::PackageName;
use uv_redacted::DisplaySafeUrl;

use crate::{DirectorySourceDist, GitSourceDist, Name, PathSourceDist, SourceDist};
use crate::{
DirectorySourceDist, GitDirectorySourceDist, GitPathSourceDist, Name, PathSourceDist,
SourceDist,
};

/// A reference to a source that can be built into a built distribution.
///
Expand Down Expand Up @@ -96,7 +99,8 @@ impl std::fmt::Display for BuildableSource<'_> {
#[derive(Debug, Clone)]
pub enum SourceUrl<'a> {
Direct(DirectSourceUrl<'a>),
Git(GitSourceUrl<'a>),
GitDirectory(GitDirectorySourceUrl<'a>),
GitPath(GitPathSourceUrl<'a>),
Path(PathSourceUrl<'a>),
Directory(DirectorySourceUrl<'a>),
}
Expand All @@ -106,7 +110,8 @@ impl SourceUrl<'_> {
pub fn url(&self) -> &DisplaySafeUrl {
match self {
Self::Direct(dist) => dist.url,
Self::Git(dist) => dist.url,
Self::GitDirectory(dist) => dist.url,
Self::GitPath(dist) => dist.url,
Self::Path(dist) => dist.url,
Self::Directory(dist) => dist.url,
}
Expand Down Expand Up @@ -141,7 +146,8 @@ impl std::fmt::Display for SourceUrl<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Direct(url) => write!(f, "{url}"),
Self::Git(url) => write!(f, "{url}"),
Self::GitDirectory(url) => write!(f, "{url}"),
Self::GitPath(url) => write!(f, "{url}"),
Self::Path(url) => write!(f, "{url}"),
Self::Directory(url) => write!(f, "{url}"),
}
Expand All @@ -162,22 +168,48 @@ impl std::fmt::Display for DirectSourceUrl<'_> {
}

#[derive(Debug, Clone)]
pub struct GitSourceUrl<'a> {
pub struct GitPathSourceUrl<'a> {
/// The URL with the revision and path fragment.
pub url: &'a VerbatimUrl,
pub git: &'a GitUrl,
pub path: Cow<'a, Path>,
pub ext: SourceDistExtension,
}

impl std::fmt::Display for GitPathSourceUrl<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{url}", url = self.url)
}
}

impl<'a> From<&'a GitPathSourceDist> for GitPathSourceUrl<'a> {
fn from(dist: &'a GitPathSourceDist) -> Self {
Self {
url: &dist.url,
git: &dist.git,
path: Cow::Borrowed(&dist.install_path),
ext: dist.ext,
}
}
}

#[derive(Debug, Clone)]
pub struct GitDirectorySourceUrl<'a> {
/// The URL with the revision and subdirectory fragment.
pub url: &'a VerbatimUrl,
pub git: &'a GitUrl,
/// The URL without the revision and subdirectory fragment.
pub subdirectory: Option<&'a Path>,
}

impl std::fmt::Display for GitSourceUrl<'_> {
impl std::fmt::Display for GitDirectorySourceUrl<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{url}", url = self.url)
}
}

impl<'a> From<&'a GitSourceDist> for GitSourceUrl<'a> {
fn from(dist: &'a GitSourceDist) -> Self {
impl<'a> From<&'a GitDirectorySourceDist> for GitDirectorySourceUrl<'a> {
fn from(dist: &'a GitDirectorySourceDist) -> Self {
Self {
url: &dist.url,
git: &dist.git,
Expand Down
24 changes: 23 additions & 1 deletion crates/uv-distribution-types/src/cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ impl CachedDist {
build_info,
path,
}),
Dist::Built(BuiltDist::GitPath(dist)) => Self::Url(CachedDirectUrlDist {
filename,
url: VerbatimParsedUrl {
parsed_url: dist.parsed_url(),
verbatim: dist.url,
},
hashes,
cache_info,
build_info,
path,
}),
Dist::Source(SourceDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {
filename,
path,
Expand All @@ -97,7 +108,18 @@ impl CachedDist {
build_info,
path,
}),
Dist::Source(SourceDist::Git(dist)) => Self::Url(CachedDirectUrlDist {
Dist::Source(SourceDist::GitDirectory(dist)) => Self::Url(CachedDirectUrlDist {
filename,
url: VerbatimParsedUrl {
parsed_url: dist.parsed_url(),
verbatim: dist.url,
},
hashes,
cache_info,
build_info,
path,
}),
Dist::Source(SourceDist::GitPath(dist)) => Self::Url(CachedDirectUrlDist {
filename,
url: VerbatimParsedUrl {
parsed_url: dist.parsed_url(),
Expand Down
4 changes: 4 additions & 0 deletions crates/uv-distribution-types/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::path::PathBuf;
use uv_normalize::PackageName;
use uv_redacted::DisplaySafeUrl;

Expand All @@ -15,6 +16,9 @@ pub enum Error {
#[error("Could not extract path segments from URL: {0}")]
MissingPathSegments(String),

#[error("Could not extract wheel filename from path: {}", _0.display())]
MissingWheelFilename(PathBuf),

#[error("Distribution not found at: {0}")]
NotFound(DisplaySafeUrl),

Expand Down
12 changes: 12 additions & 0 deletions crates/uv-distribution-types/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ pub trait Hashed {
}
}

impl Hashed for Vec<HashDigest> {
fn hashes(&self) -> &[HashDigest] {
self
}
}

impl Hashed for &[HashDigest] {
fn hashes(&self) -> &[HashDigest] {
self
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;
Expand Down
12 changes: 9 additions & 3 deletions crates/uv-distribution-types/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use uv_git_types::GitUrl;
use uv_normalize::PackageName;
use uv_pep440::Version;
use uv_pypi_types::{
HashDigest, ParsedArchiveUrl, ParsedDirectoryUrl, ParsedGitUrl, ParsedPathUrl, ParsedUrl,
HashDigest, ParsedArchiveUrl, ParsedDirectoryUrl, ParsedGitDirectoryUrl, ParsedGitPathUrl,
ParsedPathUrl, ParsedUrl,
};
use uv_redacted::DisplaySafeUrl;

Expand Down Expand Up @@ -83,7 +84,8 @@ impl VersionId {
match url {
ParsedUrl::Path(path) => Self::from_path_url(path),
ParsedUrl::Directory(directory) => Self::from_directory_url(directory),
ParsedUrl::Git(git) => Self::from_git_url(git),
ParsedUrl::GitDirectory(git) => Self::from_git_directory_url(git),
ParsedUrl::GitPath(git) => Self::from_git_path_url(git),
ParsedUrl::Archive(archive) => Self::from_archive_url(archive),
}
}
Expand Down Expand Up @@ -134,9 +136,13 @@ impl VersionId {
Self::from_directory(directory.install_path.as_ref())
}

fn from_git_url(git: &ParsedGitUrl) -> Self {
fn from_git_directory_url(git: &ParsedGitDirectoryUrl) -> Self {
Self::from_git(&git.url, git.subdirectory.as_deref())
}

fn from_git_path_url(git: &ParsedGitPathUrl) -> Self {
Self::from_git(&git.url, Some(&git.install_path))
}
}

impl Display for VersionId {
Expand Down
Loading
Loading