Use UrlString for Source struct (#5804)

I don't think this will save any time in serialization, but it should
save us some deserialization, since we only need to parse URLs for the
packages we use...
This commit is contained in:
Charlie Marsh 2024-08-06 08:58:09 -04:00 committed by GitHub
parent 3a24aecb2c
commit c59c8e080a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 119 additions and 383 deletions

View file

@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
use url::Url; use url::Url;
use pep440_rs::{VersionSpecifiers, VersionSpecifiersParseError}; use pep440_rs::{VersionSpecifiers, VersionSpecifiersParseError};
use pep508_rs::VerbatimUrl;
use pypi_types::{CoreMetadata, HashDigest, Yanked}; use pypi_types::{CoreMetadata, HashDigest, Yanked};
/// Error converting [`pypi_types::File`] to [`distribution_type::File`]. /// Error converting [`pypi_types::File`] to [`distribution_type::File`].
@ -149,6 +150,8 @@ impl Display for FileLocation {
Clone, Clone,
PartialEq, PartialEq,
Eq, Eq,
PartialOrd,
Ord,
Hash, Hash,
Serialize, Serialize,
Deserialize, Deserialize,
@ -180,6 +183,24 @@ impl From<Url> for UrlString {
} }
} }
impl From<&Url> for UrlString {
fn from(value: &Url) -> Self {
UrlString(value.to_string())
}
}
impl From<VerbatimUrl> for UrlString {
fn from(value: VerbatimUrl) -> Self {
UrlString(value.raw().to_string())
}
}
impl From<&VerbatimUrl> for UrlString {
fn from(value: &VerbatimUrl) -> Self {
UrlString(value.raw().to_string())
}
}
impl From<UrlString> for String { impl From<UrlString> for String {
fn from(value: UrlString) -> Self { fn from(value: UrlString) -> Self {
value.0 value.0

View file

@ -762,7 +762,7 @@ impl Distribution {
let wheels = self let wheels = self
.wheels .wheels
.iter() .iter()
.map(|wheel| wheel.to_registry_dist(url)) .map(|wheel| wheel.to_registry_dist(url.to_url()))
.collect(); .collect();
let reg_built_dist = RegistryBuiltDist { let reg_built_dist = RegistryBuiltDist {
wheels, wheels,
@ -784,7 +784,7 @@ impl Distribution {
Source::Direct(url, direct) => { Source::Direct(url, direct) => {
let filename: WheelFilename = self.wheels[best_wheel_index].filename.clone(); let filename: WheelFilename = self.wheels[best_wheel_index].filename.clone();
let url = Url::from(ParsedArchiveUrl { let url = Url::from(ParsedArchiveUrl {
url: url.clone(), url: url.to_url(),
subdirectory: direct.subdirectory.as_ref().map(PathBuf::from), subdirectory: direct.subdirectory.as_ref().map(PathBuf::from),
}); });
let direct_dist = DirectUrlBuiltDist { let direct_dist = DirectUrlBuiltDist {
@ -864,7 +864,7 @@ impl Distribution {
Source::Git(url, git) => { Source::Git(url, git) => {
// Reconstruct the `GitUrl` from the `GitSource`. // Reconstruct the `GitUrl` from the `GitSource`.
let git_url = let git_url =
uv_git::GitUrl::new(url.clone(), GitReference::from(git.kind.clone())) uv_git::GitUrl::new(url.to_url(), GitReference::from(git.kind.clone()))
.with_precise(git.precise); .with_precise(git.precise);
// Reconstruct the PEP 508-compatible URL from the `GitSource`. // Reconstruct the PEP 508-compatible URL from the `GitSource`.
@ -883,7 +883,7 @@ impl Distribution {
} }
Source::Direct(url, direct) => { Source::Direct(url, direct) => {
let url = Url::from(ParsedArchiveUrl { let url = Url::from(ParsedArchiveUrl {
url: url.clone(), url: url.to_url(),
subdirectory: direct.subdirectory.as_ref().map(PathBuf::from), subdirectory: direct.subdirectory.as_ref().map(PathBuf::from),
}); });
let direct_dist = DirectUrlSourceDist { let direct_dist = DirectUrlSourceDist {
@ -920,7 +920,7 @@ impl Distribution {
url: FileLocation::AbsoluteUrl(file_url.clone()), url: FileLocation::AbsoluteUrl(file_url.clone()),
yanked: None, yanked: None,
}); });
let index = IndexUrl::Url(VerbatimUrl::from_url(url.clone())); let index = IndexUrl::Url(VerbatimUrl::from_url(url.to_url()));
let reg_dist = RegistrySourceDist { let reg_dist = RegistrySourceDist {
name: self.id.name.clone(), name: self.id.name.clone(),
@ -962,7 +962,7 @@ impl Distribution {
// Add any wheels. // Add any wheels.
for wheel in &self.wheels { for wheel in &self.wheels {
let hash = wheel.hash.as_ref().map(|h| h.0.clone()); let hash = wheel.hash.as_ref().map(|h| h.0.clone());
let wheel = wheel.to_registry_dist(url); let wheel = wheel.to_registry_dist(url.to_url());
let compat = let compat =
WheelCompatibility::Compatible(HashComparison::Matched, None, None); WheelCompatibility::Compatible(HashComparison::Matched, None, None);
prioritized_dist.insert_built(wheel, hash, compat); prioritized_dist.insert_built(wheel, hash, compat);
@ -1178,7 +1178,7 @@ impl Distribution {
match &self.id.source { match &self.id.source {
Source::Git(url, git) => Some(ResolvedRepositoryReference { Source::Git(url, git) => Some(ResolvedRepositoryReference {
reference: RepositoryReference { reference: RepositoryReference {
url: RepositoryUrl::new(url), url: RepositoryUrl::new(&url.to_url()),
reference: GitReference::from(git.kind.clone()), reference: GitReference::from(git.kind.clone()),
}, },
sha: git.precise, sha: git.precise,
@ -1374,9 +1374,9 @@ impl From<DistributionId> for DistributionIdForDependency {
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, serde::Deserialize)] #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, serde::Deserialize)]
#[serde(try_from = "SourceWire")] #[serde(try_from = "SourceWire")]
enum Source { enum Source {
Registry(Url), Registry(UrlString),
Git(Url, GitSource), Git(UrlString, GitSource),
Direct(Url, DirectSource), Direct(UrlString, DirectSource),
Path(PathBuf), Path(PathBuf),
Directory(PathBuf), Directory(PathBuf),
Editable(PathBuf), Editable(PathBuf),
@ -1435,14 +1435,14 @@ impl Source {
fn from_direct_built_dist(direct_dist: &DirectUrlBuiltDist) -> Source { fn from_direct_built_dist(direct_dist: &DirectUrlBuiltDist) -> Source {
Source::Direct( Source::Direct(
direct_dist.url.to_url(), UrlString::from(&direct_dist.url),
DirectSource { subdirectory: None }, DirectSource { subdirectory: None },
) )
} }
fn from_direct_source_dist(direct_dist: &DirectUrlSourceDist) -> Source { fn from_direct_source_dist(direct_dist: &DirectUrlSourceDist) -> Source {
Source::Direct( Source::Direct(
direct_dist.url.to_url(), UrlString::from(&direct_dist.url),
DirectSource { DirectSource {
subdirectory: direct_dist subdirectory: direct_dist
.subdirectory .subdirectory
@ -1470,23 +1470,14 @@ impl Source {
} }
fn from_index_url(index_url: &IndexUrl) -> Source { fn from_index_url(index_url: &IndexUrl) -> Source {
/// Redact a URL by removing any username and password. // Remove any sensitive credentials from the index URL.
fn redact(mut url: Url) -> Result<Url, ()> { let redacted = index_url.redacted();
url.set_username("")?;
url.set_password(None)?;
Ok(url)
}
match *index_url { match *index_url {
IndexUrl::Pypi(ref verbatim_url) => { IndexUrl::Pypi(_) => Source::Registry(UrlString::from(redacted.as_ref())),
Source::Registry(redact(verbatim_url.to_url()).expect("Could not redact URL")) IndexUrl::Url(_) => Source::Registry(UrlString::from(redacted.as_ref())),
}
IndexUrl::Url(ref verbatim_url) => {
Source::Registry(redact(verbatim_url.to_url()).expect("Could not redact URL"))
}
// TODO(konsti): Retain path on index url without converting to URL. // TODO(konsti): Retain path on index url without converting to URL.
IndexUrl::Path(ref verbatim_url) => Source::Path( IndexUrl::Path(_) => Source::Path(
verbatim_url redacted
.to_file_path() .to_file_path()
.expect("Could not convert index URL to path"), .expect("Could not convert index URL to path"),
), ),
@ -1495,7 +1486,7 @@ impl Source {
fn from_git_dist(git_dist: &GitSourceDist) -> Source { fn from_git_dist(git_dist: &GitSourceDist) -> Source {
Source::Git( Source::Git(
locked_git_url(git_dist), UrlString::from(locked_git_url(git_dist)),
GitSource { GitSource {
kind: GitSourceKind::from(git_dist.git.reference().clone()), kind: GitSourceKind::from(git_dist.git.reference().clone()),
precise: git_dist.git.precise().expect("precise commit"), precise: git_dist.git.precise().expect("precise commit"),
@ -1512,13 +1503,13 @@ impl Source {
let mut source_table = InlineTable::new(); let mut source_table = InlineTable::new();
match *self { match *self {
Source::Registry(ref url) => { Source::Registry(ref url) => {
source_table.insert("registry", Value::from(url.as_str())); source_table.insert("registry", Value::from(url.as_ref()));
} }
Source::Git(ref url, _) => { Source::Git(ref url, _) => {
source_table.insert("git", Value::from(url.as_str())); source_table.insert("git", Value::from(url.as_ref()));
} }
Source::Direct(ref url, DirectSource { ref subdirectory }) => { Source::Direct(ref url, DirectSource { ref subdirectory }) => {
source_table.insert("url", Value::from(url.as_str())); source_table.insert("url", Value::from(url.as_ref()));
if let Some(ref subdirectory) = *subdirectory { if let Some(ref subdirectory) = *subdirectory {
source_table.insert("subdirectory", Value::from(subdirectory)); source_table.insert("subdirectory", Value::from(subdirectory));
} }
@ -1588,13 +1579,13 @@ impl Source {
#[serde(untagged)] #[serde(untagged)]
enum SourceWire { enum SourceWire {
Registry { Registry {
registry: Url, registry: UrlString,
}, },
Git { Git {
git: String, git: String,
}, },
Direct { Direct {
url: Url, url: UrlString,
#[serde(default)] #[serde(default)]
subdirectory: Option<String>, subdirectory: Option<String>,
}, },
@ -1635,7 +1626,7 @@ impl TryFrom<SourceWire> for Source {
}, },
}) })
.map_err(LockErrorKind::InvalidGitSourceUrl)?; .map_err(LockErrorKind::InvalidGitSourceUrl)?;
Ok(Source::Git(url, git_source)) Ok(Source::Git(UrlString::from(url), git_source))
} }
Direct { url, subdirectory } => Ok(Source::Direct(url, DirectSource { subdirectory })), Direct { url, subdirectory } => Ok(Source::Direct(url, DirectSource { subdirectory })),
Path { path } => Ok(Source::Path(path.into())), Path { path } => Ok(Source::Path(path.into())),
@ -2092,7 +2083,7 @@ impl Wheel {
} }
} }
fn to_registry_dist(&self, url: &Url) -> RegistryBuiltWheel { fn to_registry_dist(&self, url: Url) -> RegistryBuiltWheel {
let filename: WheelFilename = self.filename.clone(); let filename: WheelFilename = self.filename.clone();
let file = Box::new(distribution_types::File { let file = Box::new(distribution_types::File {
dist_info_metadata: false, dist_info_metadata: false,
@ -2104,7 +2095,7 @@ impl Wheel {
url: FileLocation::AbsoluteUrl(self.url.clone()), url: FileLocation::AbsoluteUrl(self.url.clone()),
yanked: None, yanked: None,
}); });
let index = IndexUrl::Url(VerbatimUrl::from_url(url.clone())); let index = IndexUrl::Url(VerbatimUrl::from_url(url));
RegistryBuiltWheel { RegistryBuiltWheel {
filename, filename,
file, file,
@ -2218,7 +2209,7 @@ impl Dependency {
}, },
Source::Git(repository, git) => { Source::Git(repository, git) => {
let git_url = let git_url =
uv_git::GitUrl::new(repository.clone(), GitReference::from(git.kind.clone())) uv_git::GitUrl::new(repository.to_url(), GitReference::from(git.kind.clone()))
.with_precise(git.precise); .with_precise(git.precise);
let parsed_url = ParsedUrl::Git(ParsedGitUrl { let parsed_url = ParsedUrl::Git(ParsedGitUrl {
@ -2229,7 +2220,7 @@ impl Dependency {
} }
Source::Direct(url, direct) => { Source::Direct(url, direct) => {
let parsed_url = ParsedUrl::Archive(ParsedArchiveUrl { let parsed_url = ParsedUrl::Archive(ParsedArchiveUrl {
url: url.clone(), url: url.to_url(),
subdirectory: direct.subdirectory.as_ref().map(PathBuf::from), subdirectory: direct.subdirectory.as_ref().map(PathBuf::from),
}); });
RequirementSource::from_verbatim_parsed_url(parsed_url) RequirementSource::from_verbatim_parsed_url(parsed_url)

View file

@ -18,21 +18,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: None, sdist: None,
@ -74,21 +62,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 0, }: 0,
}, },

View file

@ -18,21 +18,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: None, sdist: None,
@ -81,21 +69,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 0, }: 0,
}, },

View file

@ -18,21 +18,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: Some( sdist: Some(
@ -68,21 +56,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: Some( sdist: Some(
@ -115,21 +91,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
extra: {}, extra: {},
@ -147,21 +111,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 0, }: 0,
DistributionId { DistributionId {
@ -170,21 +122,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 1, }: 1,
}, },

View file

@ -18,21 +18,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: Some( sdist: Some(
@ -68,21 +56,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: Some( sdist: Some(
@ -115,21 +91,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
extra: {}, extra: {},
@ -147,21 +111,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 0, }: 0,
DistributionId { DistributionId {
@ -170,21 +122,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 1, }: 1,
}, },

View file

@ -18,21 +18,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: Some( sdist: Some(
@ -68,21 +56,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
sdist: Some( sdist: Some(
@ -115,21 +91,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}, },
extra: {}, extra: {},
@ -147,21 +111,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 0, }: 0,
DistributionId { DistributionId {
@ -170,21 +122,9 @@ Ok(
), ),
version: "0.1.0", version: "0.1.0",
source: Registry( source: Registry(
Url { UrlString(
scheme: "https", "https://pypi.org/simple",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"pypi.org",
),
),
port: None,
path: "/simple",
query: None,
fragment: None,
},
), ),
}: 1, }: 1,
}, },

View file

@ -18,21 +18,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Direct( source: Direct(
Url { UrlString(
scheme: "https", "https://burntsushi.net",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"burntsushi.net",
),
),
port: None,
path: "/",
query: None,
fragment: None,
},
DirectSource { DirectSource {
subdirectory: Some( subdirectory: Some(
"wat/foo/bar", "wat/foo/bar",
@ -55,21 +43,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Direct( source: Direct(
Url { UrlString(
scheme: "https", "https://burntsushi.net",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"burntsushi.net",
),
),
port: None,
path: "/",
query: None,
fragment: None,
},
DirectSource { DirectSource {
subdirectory: Some( subdirectory: Some(
"wat/foo/bar", "wat/foo/bar",

View file

@ -18,21 +18,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Direct( source: Direct(
Url { UrlString(
scheme: "https", "https://burntsushi.net",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"burntsushi.net",
),
),
port: None,
path: "/",
query: None,
fragment: None,
},
DirectSource { DirectSource {
subdirectory: None, subdirectory: None,
}, },
@ -53,21 +41,9 @@ Ok(
), ),
version: "4.3.0", version: "4.3.0",
source: Direct( source: Direct(
Url { UrlString(
scheme: "https", "https://burntsushi.net",
cannot_be_a_base: false, ),
username: "",
password: None,
host: Some(
Domain(
"burntsushi.net",
),
),
port: None,
path: "/",
query: None,
fragment: None,
},
DirectSource { DirectSource {
subdirectory: None, subdirectory: None,
}, },