Use filename trait for WheelWire conversion (#3651)

## Summary

The main motivation here is that the `.filename()` method that we
implement on `Url` will do URL decoding for the last segment, which we
were missing here.

The errors are a bit awkward, because in
`crates/uv-resolver/src/lock.rs`, we wrap in `failed to extract filename
from URL: {url}`, so in theory we want the underlying errors to _omit_
the URL? But sometimes they use `#[error(transparent)]`?
This commit is contained in:
Charlie Marsh 2024-05-20 09:25:31 -04:00 committed by GitHub
parent 657eebd50b
commit f3965fef5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 19 additions and 15 deletions

View file

@ -14,8 +14,11 @@ pub enum Error {
#[error(transparent)]
WheelFilename(#[from] distribution_filename::WheelFilenameError),
#[error("Unable to extract filename from URL: {0}")]
UrlFilename(Url),
#[error("Unable to extract file path from URL: {0}")]
MissingFilePath(Url),
#[error("Could not extract path segments from URL: {0}")]
MissingPathSegments(Url),
#[error("Distribution not found at: {0}")]
NotFound(Url),

View file

@ -709,13 +709,15 @@ impl RemoteSource for File {
impl RemoteSource for Url {
fn filename(&self) -> Result<Cow<'_, str>, Error> {
// Identify the last segment of the URL as the filename.
let filename = self
let path_segments = self
.path_segments()
.and_then(Iterator::last)
.ok_or_else(|| Error::UrlFilename(self.clone()))?;
.ok_or_else(|| Error::MissingPathSegments(self.clone()))?;
// This is guaranteed by the contract of `Url::path_segments`.
let last = path_segments.last().expect("path segments is non-empty");
// Decode the filename, which may be percent-encoded.
let filename = urlencoding::decode(filename)?;
let filename = urlencoding::decode(last)?;
Ok(filename)
}