Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for direct archive dependencies in Git #10072

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 @@ -17,6 +17,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 @@ -144,6 +144,9 @@ pub enum ErrorKind {
#[error(transparent)]
JoinRelativeUrl(#[from] uv_pypi_types::JoinRelativeError),

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

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

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 @@ -8,6 +8,7 @@ use std::collections::BTreeMap;
use std::fmt::Debug;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
use tracing::{info_span, instrument, trace, warn, Instrument};
use url::Url;
Expand All @@ -19,6 +20,7 @@ use uv_distribution_filename::{DistFilename, SourceDistFilename, WheelFilename};
use uv_distribution_types::{
BuiltDist, File, FileLocation, Index, IndexCapabilities, 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 @@ -446,7 +448,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 @@ -539,6 +543,36 @@ impl RegistryClient {
)
})?
}
BuiltDist::GitPath(wheel) => {
// Fetch the Git repository.
let fetch = git
.fetch(
&wheel.git,
self.uncached_client(&wheel.url).clone(),
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
7 changes: 6 additions & 1 deletion crates/uv-client/tests/it/remote_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use uv_cache::Cache;
use uv_client::RegistryClientBuilder;
use uv_distribution_filename::WheelFilename;
use uv_distribution_types::{BuiltDist, DirectUrlBuiltDist, IndexCapabilities};
use uv_git::GitResolver;
use uv_pep508::VerbatimUrl;

#[tokio::test]
Expand All @@ -24,8 +25,12 @@ async fn remote_metadata_with_and_without_cache() -> Result<()> {
location: Url::parse(url).unwrap(),
url: VerbatimUrl::from_str(url).unwrap(),
});
let resolver = GitResolver::default();
let capabilities = IndexCapabilities::default();
let metadata = client.wheel_metadata(&dist, &capabilities).await.unwrap();
let metadata = client
.wheel_metadata(&dist, &resolver, &capabilities, None)
.await
.unwrap();
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-client = { workspace = true }
uv-distribution-filename = { workspace = true }
uv-distribution-types = { workspace = true }
uv-extract = { workspace = true, optional = 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::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;

Expand All @@ -21,6 +22,7 @@ pub(crate) struct WheelMetadataArgs {
pub(crate) async fn wheel_metadata(args: WheelMetadataArgs) -> Result<()> {
let cache = Cache::try_from(args.cache_args)?.init()?;
let client = RegistryClientBuilder::new(cache).build();
let resolver = GitResolver::default();
let capabilities = IndexCapabilities::default();

let filename = WheelFilename::from_str(&args.url.filename()?)?;
Expand All @@ -36,7 +38,9 @@ pub(crate) async fn wheel_metadata(args: WheelMetadataArgs) -> Result<()> {
location: archive.url,
url: args.url,
}),
&resolver,
&capabilities,
None,
)
.await?;
println!("{metadata:?}");
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 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 @@ -88,7 +91,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 @@ -98,7 +102,8 @@ impl SourceUrl<'_> {
pub fn url(&self) -> &Url {
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 All @@ -122,7 +127,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 @@ -143,22 +149,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
20 changes: 19 additions & 1 deletion crates/uv-distribution-types/src/cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ impl CachedDist {
editable: false,
r#virtual: false,
}),
Dist::Built(BuiltDist::GitPath(dist)) => Self::Url(CachedDirectUrlDist {
filename,
url: dist.url,
hashes,
cache_info,
path,
editable: false,
r#virtual: false,
}),
Dist::Source(SourceDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {
filename,
path,
Expand All @@ -90,7 +99,16 @@ impl CachedDist {
editable: false,
r#virtual: false,
}),
Dist::Source(SourceDist::Git(dist)) => Self::Url(CachedDirectUrlDist {
Dist::Source(SourceDist::GitDirectory(dist)) => Self::Url(CachedDirectUrlDist {
filename,
url: dist.url,
hashes,
cache_info,
path,
editable: false,
r#virtual: false,
}),
Dist::Source(SourceDist::GitPath(dist)) => Self::Url(CachedDirectUrlDist {
filename,
url: dist.url,
hashes,
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 url::Url;

use uv_normalize::PackageName;
Expand All @@ -16,6 +17,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(Url),

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 @@ -82,3 +82,15 @@ pub trait Hashed {
}
}
}

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

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