Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 0 additions & 1 deletion Cargo.lock

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

4 changes: 1 addition & 3 deletions crates/uv-distribution-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,9 +714,7 @@ impl GitSourceDist {
/// Return the [`ParsedUrl`] for the distribution.
pub fn parsed_url(&self) -> ParsedUrl {
ParsedUrl::Git(ParsedGitUrl::from_source(
self.git.repository().clone(),
self.git.reference().clone(),
self.git.precise(),
(*self.git).clone(),
self.subdirectory.clone(),
))
}
Expand Down
4 changes: 1 addition & 3 deletions crates/uv-distribution-types/src/resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,8 @@ impl From<&ResolvedDist> for RequirementSource {
}
}
Dist::Source(SourceDist::Git(sdist)) => RequirementSource::Git {
git: (*sdist.git).clone(),
url: sdist.url.clone(),
repository: sdist.git.repository().clone(),
reference: sdist.git.reference().clone(),
precise: sdist.git.precise(),
subdirectory: sdist.subdirectory.clone(),
},
Dist::Source(SourceDist::Path(sdist)) => RequirementSource::Path {
Expand Down
16 changes: 6 additions & 10 deletions crates/uv-distribution/src/metadata/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use url::Url;

use uv_distribution_filename::DistExtension;
use uv_distribution_types::{Index, IndexLocations, IndexName, Origin};
use uv_git_types::GitReference;
use uv_git_types::{GitReference, GitUrl, GitUrlParseError};
use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep440::VersionSpecifiers;
use uv_pep508::{looks_like_git_repository, MarkerTree, VerbatimUrl, VersionOrUrl};
Expand Down Expand Up @@ -291,9 +291,7 @@ impl LoweredRequirement {
.expect("Workspace member must be relative");
let subdirectory = uv_fs::normalize_path_buf(subdirectory);
RequirementSource::Git {
repository: git_member.git_source.git.repository().clone(),
reference: git_member.git_source.git.reference().clone(),
precise: git_member.git_source.git.precise(),
git: git_member.git_source.git.clone(),
subdirectory: if subdirectory == PathBuf::new() {
None
} else {
Expand Down Expand Up @@ -497,6 +495,8 @@ pub enum LoweringError {
UndeclaredWorkspacePackage(PackageName),
#[error("Can only specify one of: `rev`, `tag`, or `branch`")]
MoreThanOneGitRef,
#[error(transparent)]
GitUrlParse(#[from] GitUrlParseError),
#[error("Package `{0}` references an undeclared index: `{1}`")]
MissingIndex(PackageName, IndexName),
#[error("Workspace members are not allowed in non-workspace contexts")]
Expand Down Expand Up @@ -575,9 +575,7 @@ fn git_source(

Ok(RequirementSource::Git {
url,
repository,
reference,
precise: None,
git: GitUrl::from_reference(repository, reference)?,
subdirectory,
})
}
Expand Down Expand Up @@ -679,9 +677,7 @@ fn path_source(
.expect("Workspace member must be relative");
let subdirectory = uv_fs::normalize_path_buf(subdirectory);
return Ok(RequirementSource::Git {
repository: git_member.git_source.git.repository().clone(),
reference: git_member.git_source.git.reference().clone(),
precise: git_member.git_source.git.precise(),
git: git_member.git_source.git.clone(),
subdirectory: if subdirectory == PathBuf::new() {
None
} else {
Expand Down
53 changes: 41 additions & 12 deletions crates/uv-git-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
pub use crate::github::GitHubRepository;
pub use crate::oid::{GitOid, OidParseError};
pub use crate::reference::GitReference;

use thiserror::Error;
use url::Url;

mod github;
mod oid;
mod reference;

#[derive(Debug, Error)]
pub enum GitUrlParseError {
#[error("Unsupported Git URL scheme `{0}:` in `{1}`, only `https:`, `ssh:` and `file:` are supported")]
UnsupportedGitScheme(String, Url),
}

/// A URL reference to a Git repository.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash, Ord)]
pub struct GitUrl {
Expand All @@ -21,21 +29,42 @@ pub struct GitUrl {

impl GitUrl {
/// Create a new [`GitUrl`] from a repository URL and a reference.
pub fn from_reference(repository: Url, reference: GitReference) -> Self {
Self {
repository,
reference,
precise: None,
}
pub fn from_reference(
repository: Url,
reference: GitReference,
) -> Result<Self, GitUrlParseError> {
Self::from_fields(repository, reference, None)
}

/// Create a new [`GitUrl`] from a repository URL and a precise commit.
pub fn from_commit(repository: Url, reference: GitReference, precise: GitOid) -> Self {
Self {
pub fn from_commit(
repository: Url,
reference: GitReference,
precise: GitOid,
) -> Result<Self, GitUrlParseError> {
Self::from_fields(repository, reference, Some(precise))
}

/// Create a new [`GitUrl`] from a repository URL and a precise commit, if known.
pub fn from_fields(
repository: Url,
reference: GitReference,
precise: Option<GitOid>,
) -> Result<Self, GitUrlParseError> {
match repository.scheme() {
"https" | "ssh" | "file" => {}
unsupported => {
return Err(GitUrlParseError::UnsupportedGitScheme(
unsupported.to_string(),
repository,
))
}
}
Ok(Self {
repository,
reference,
precise: Some(precise),
}
precise,
})
}

/// Set the precise [`GitOid`] to use for this Git URL.
Expand Down Expand Up @@ -69,7 +98,7 @@ impl GitUrl {
}

impl TryFrom<Url> for GitUrl {
type Error = OidParseError;
type Error = GitUrlParseError;

/// Initialize a [`GitUrl`] source from a URL.
fn try_from(mut url: Url) -> Result<Self, Self::Error> {
Expand All @@ -89,7 +118,7 @@ impl TryFrom<Url> for GitUrl {
url.set_path(&prefix);
}

Ok(Self::from_reference(url, reference))
Self::from_reference(url, reference)
}
}

Expand Down
16 changes: 9 additions & 7 deletions crates/uv-installer/src/satisfies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,7 @@ impl RequirementSatisfaction {
}
RequirementSource::Git {
url: _,
repository: requested_repository,
reference: _,
precise: requested_precise,
git: requested_git,
subdirectory: requested_subdirectory,
} => {
let InstalledDist::Url(InstalledDirectUrlDist { direct_url, .. }) = &distribution
Expand Down Expand Up @@ -129,21 +127,25 @@ impl RequirementSatisfaction {
}

if !RepositoryUrl::parse(installed_url).is_ok_and(|installed_url| {
installed_url == RepositoryUrl::new(requested_repository)
installed_url == RepositoryUrl::new(requested_git.repository())
}) {
debug!(
"Repository mismatch: {:?} vs. {:?}",
installed_url, requested_repository
installed_url,
requested_git.repository()
);
return Ok(Self::Mismatch);
}

// TODO(charlie): It would be more consistent for us to compare the requested
// revisions here.
if installed_precise.as_deref() != requested_precise.as_ref().map(GitOid::as_str) {
if installed_precise.as_deref()
!= requested_git.precise().as_ref().map(GitOid::as_str)
{
debug!(
"Precise mismatch: {:?} vs. {:?}",
installed_precise, requested_precise
installed_precise,
requested_git.precise()
);
return Ok(Self::OutOfDate);
}
Expand Down
21 changes: 5 additions & 16 deletions crates/uv-pypi-types/src/parsed_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use thiserror::Error;
use url::{ParseError, Url};

use uv_distribution_filename::{DistExtension, ExtensionError};
use uv_git_types::{GitOid, GitReference, GitUrl, OidParseError};
use uv_git_types::{GitUrl, GitUrlParseError};
use uv_pep508::{
looks_like_git_repository, Pep508Url, UnnamedRequirementUrl, VerbatimUrl, VerbatimUrlError,
};
Expand All @@ -22,8 +22,8 @@ pub enum ParsedUrlError {
},
#[error("Invalid path in file URL: `{0}`")]
InvalidFileUrl(String),
#[error("Failed to parse Git reference from URL: `{0}`")]
GitOidParse(String, #[source] OidParseError),
#[error(transparent)]
GitUrlParse(#[from] GitUrlParseError),
#[error("Not a valid URL: `{0}`")]
UrlParse(String, #[source] ParseError),
#[error(transparent)]
Expand Down Expand Up @@ -244,17 +244,7 @@ pub struct ParsedGitUrl {

impl ParsedGitUrl {
/// Construct a [`ParsedGitUrl`] from a Git requirement source.
pub fn from_source(
repository: Url,
reference: GitReference,
precise: Option<GitOid>,
subdirectory: Option<PathBuf>,
) -> Self {
let url = if let Some(precise) = precise {
GitUrl::from_commit(repository, reference, precise)
} else {
GitUrl::from_reference(repository, reference)
};
pub fn from_source(url: GitUrl, subdirectory: Option<PathBuf>) -> Self {
Self { url, subdirectory }
}
}
Expand All @@ -274,8 +264,7 @@ impl TryFrom<Url> for ParsedGitUrl {
.strip_prefix("git+")
.unwrap_or(url_in.as_str());
let url = Url::parse(url).map_err(|err| ParsedUrlError::UrlParse(url.to_string(), err))?;
let url = GitUrl::try_from(url)
.map_err(|err| ParsedUrlError::GitOidParse(url_in.to_string(), err))?;
let url = GitUrl::try_from(url)?;
Ok(Self { url, subdirectory })
}
}
Expand Down
Loading
Loading