Eagerly reject unsupported Git schemes (#11514)
Initially, we were limiting Git schemes to HTTPS and SSH as only supported schemes. We lost this validation in #3429. This incidentally allowed file schemes, which apparently work with Git out of the box. A caveat for this is that in tool.uv.sources, we parse the git field always as URL. This caused a problem with #11425: repo = { git = 'c:\path\to\repo', rev = "xxxxx" } was parsed as a URL where c: is the scheme, causing a bad error message down the line. This PR: * Puts Git URL validation back in place. It bans everything but HTTPS, SSH, and file URLs. This could be a breaking change, if users were using a git transport protocol were not aware of, even though never intentionally supported. * Allows file: URL in Git: This seems to be supported by Git and we were supporting it albeit unintentionally, so it's reasonable to continue to support it. * It does not allow relative paths in the git field in tool.uv.sources. Absolute file URLs are supported, whether we want relative file URLs for Git too should be discussed separately. Closes #3429: We reject the input with a proper error message, while hinting the user towards file:. If there's still desire for relative path support, we can keep it open. --------- Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
@@ -1,12 +1,22 @@
|
||||
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}` (expected one of `https:`, `ssh:`, or `file:`)"
|
||||
)]
|
||||
UnsupportedGitScheme(String, Url),
|
||||
}
|
||||
|
||||
/// A URL reference to a Git repository.
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash, Ord)]
|
||||
pub struct GitUrl {
|
||||
@@ -21,21 +31,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.
|
||||
@@ -69,7 +100,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> {
|
||||
@@ -89,7 +120,7 @@ impl TryFrom<Url> for GitUrl {
|
||||
url.set_path(&prefix);
|
||||
}
|
||||
|
||||
Ok(Self::from_reference(url, reference))
|
||||
Self::from_reference(url, reference)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user