Add a reusable path-or-URL parser (#14712)
Reviewing #14687, I noticed that we had implemented a `Url::from_url_or_path`-like function, but it wasn't reusable. This change `Verbatim::from_url_or_path` so we can use it in other places too. The PEP 508 parser is an odd place for this, but that's where `VerbatimUrl` and `Scheme` are already living.
This commit is contained in:
@@ -39,33 +39,8 @@ impl IndexUrl {
|
||||
/// If no root directory is provided, relative paths are resolved against the current working
|
||||
/// directory.
|
||||
pub fn parse(path: &str, root_dir: Option<&Path>) -> Result<Self, IndexUrlError> {
|
||||
let url = match split_scheme(path) {
|
||||
Some((scheme, ..)) => {
|
||||
match Scheme::parse(scheme) {
|
||||
Some(_) => {
|
||||
// Ex) `https://pypi.org/simple`
|
||||
VerbatimUrl::parse_url(path)?
|
||||
}
|
||||
None => {
|
||||
// Ex) `C:\Users\user\index`
|
||||
if let Some(root_dir) = root_dir {
|
||||
VerbatimUrl::from_path(path, root_dir)?
|
||||
} else {
|
||||
VerbatimUrl::from_absolute_path(std::path::absolute(path)?)?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// Ex) `/Users/user/index`
|
||||
if let Some(root_dir) = root_dir {
|
||||
VerbatimUrl::from_path(path, root_dir)?
|
||||
} else {
|
||||
VerbatimUrl::from_absolute_path(std::path::absolute(path)?)?
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(Self::from(url.with_given(path)))
|
||||
let url = VerbatimUrl::from_url_or_path(path, root_dir)?;
|
||||
Ok(Self::from(url))
|
||||
}
|
||||
|
||||
/// Return the root [`Url`] of the index, if applicable.
|
||||
|
||||
@@ -58,6 +58,48 @@ impl VerbatimUrl {
|
||||
})
|
||||
}
|
||||
|
||||
/// Convert a [`VerbatimUrl`] from a path or a URL.
|
||||
///
|
||||
/// If no root directory is provided, relative paths are resolved against the current working
|
||||
/// directory.
|
||||
pub fn from_url_or_path(
|
||||
input: &str,
|
||||
root_dir: Option<&Path>,
|
||||
) -> Result<Self, VerbatimUrlError> {
|
||||
let url = match split_scheme(input) {
|
||||
Some((scheme, ..)) => {
|
||||
match Scheme::parse(scheme) {
|
||||
Some(_) => {
|
||||
// Ex) `https://pypi.org/simple`
|
||||
Self::parse_url(input)?
|
||||
}
|
||||
None => {
|
||||
// Ex) `C:\Users\user\index`
|
||||
if let Some(root_dir) = root_dir {
|
||||
Self::from_path(input, root_dir)?
|
||||
} else {
|
||||
let absolute_path = std::path::absolute(input).map_err(|err| {
|
||||
VerbatimUrlError::Absolute(input.to_string(), err)
|
||||
})?;
|
||||
Self::from_absolute_path(absolute_path)?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// Ex) `/Users/user/index`
|
||||
if let Some(root_dir) = root_dir {
|
||||
Self::from_path(input, root_dir)?
|
||||
} else {
|
||||
let absolute_path = std::path::absolute(input)
|
||||
.map_err(|err| VerbatimUrlError::Absolute(input.to_string(), err))?;
|
||||
Self::from_absolute_path(absolute_path)?
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(url.with_given(input))
|
||||
}
|
||||
|
||||
/// Parse a URL from an absolute or relative path.
|
||||
#[cfg(feature = "non-pep508-extensions")] // PEP 508 arguably only allows absolute file URLs.
|
||||
pub fn from_path(
|
||||
@@ -362,6 +404,10 @@ pub enum VerbatimUrlError {
|
||||
#[error("path could not be normalized: {0}")]
|
||||
Normalization(PathBuf, #[source] std::io::Error),
|
||||
|
||||
/// Received a path that could not be converted to an absolute path.
|
||||
#[error("path could not be converted to an absolute path: {0}")]
|
||||
Absolute(String, #[source] std::io::Error),
|
||||
|
||||
/// Received a path that could not be normalized.
|
||||
#[cfg(not(feature = "non-pep508-extensions"))]
|
||||
#[error("Not a URL (missing scheme): {0}")]
|
||||
|
||||
Reference in New Issue
Block a user