mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-21 07:42:05 +00:00
Expand environment variables in -r
and -c
subfile paths (#2143)
## Summary This PR expands environment variables in `-r` and `-c` paths _within_ requirements files. We already do this for `@` URL references and others. Closes https://github.com/astral-sh/uv/issues/1473.
This commit is contained in:
parent
bf07c7bb72
commit
836b90c760
4 changed files with 59 additions and 15 deletions
|
@ -45,7 +45,7 @@ use pep440_rs::{Version, VersionSpecifier, VersionSpecifiers};
|
|||
use uv_fs::normalize_url_path;
|
||||
// Parity with the crates.io version of pep508_rs
|
||||
pub use uv_normalize::{ExtraName, InvalidNameError, PackageName};
|
||||
pub use verbatim_url::{split_scheme, Scheme, VerbatimUrl};
|
||||
pub use verbatim_url::{expand_path_vars, split_scheme, Scheme, VerbatimUrl};
|
||||
|
||||
mod marker;
|
||||
mod verbatim_url;
|
||||
|
|
|
@ -32,7 +32,7 @@ pub struct VerbatimUrl {
|
|||
impl VerbatimUrl {
|
||||
/// Parse a URL from a string, expanding any environment variables.
|
||||
pub fn parse(given: impl AsRef<str>) -> Result<Self, ParseError> {
|
||||
let url = Url::parse(&expand_env_vars(given.as_ref(), true))?;
|
||||
let url = Url::parse(&expand_env_vars(given.as_ref(), Escape::Url))?;
|
||||
Ok(Self { url, given: None })
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ impl VerbatimUrl {
|
|||
#[cfg(feature = "non-pep508-extensions")] // PEP 508 arguably only allows absolute file URLs.
|
||||
pub fn parse_path(path: impl AsRef<str>, working_dir: impl AsRef<Path>) -> Self {
|
||||
// Expand any environment variables.
|
||||
let path = PathBuf::from(expand_env_vars(path.as_ref(), false).as_ref());
|
||||
let path = PathBuf::from(expand_env_vars(path.as_ref(), Escape::Path).as_ref());
|
||||
|
||||
// Convert the path to an absolute path, if necessary.
|
||||
let path = if path.is_absolute() {
|
||||
|
@ -73,7 +73,7 @@ impl VerbatimUrl {
|
|||
/// Parse a URL from an absolute path.
|
||||
pub fn parse_absolute_path(path: impl AsRef<str>) -> Result<Self, VerbatimUrlError> {
|
||||
// Expand any environment variables.
|
||||
let path = PathBuf::from(expand_env_vars(path.as_ref(), false).as_ref());
|
||||
let path = PathBuf::from(expand_env_vars(path.as_ref(), Escape::Path).as_ref());
|
||||
|
||||
// Convert the path to an absolute path, if necessary.
|
||||
let path = if path.is_absolute() {
|
||||
|
@ -160,6 +160,15 @@ pub enum VerbatimUrlError {
|
|||
RelativePath(PathBuf),
|
||||
}
|
||||
|
||||
/// Whether to apply percent-encoding when expanding environment variables.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum Escape {
|
||||
/// Apply percent-encoding.
|
||||
Url,
|
||||
/// Do not apply percent-encoding.
|
||||
Path,
|
||||
}
|
||||
|
||||
/// Expand all available environment variables.
|
||||
///
|
||||
/// This is modeled off of pip's environment variable expansion, which states:
|
||||
|
@ -175,7 +184,7 @@ pub enum VerbatimUrlError {
|
|||
/// Valid characters in variable names follow the `POSIX standard
|
||||
/// <http://pubs.opengroup.org/onlinepubs/9699919799/>`_ and are limited
|
||||
/// to uppercase letter, digits and the `_` (underscore).
|
||||
fn expand_env_vars(s: &str, escape: bool) -> Cow<'_, str> {
|
||||
fn expand_env_vars(s: &str, escape: Escape) -> Cow<'_, str> {
|
||||
// Generate the project root, to be used via the `${PROJECT_ROOT}`
|
||||
// environment variable.
|
||||
static PROJECT_ROOT_FRAGMENT: Lazy<String> = Lazy::new(|| {
|
||||
|
@ -190,18 +199,20 @@ fn expand_env_vars(s: &str, escape: bool) -> Cow<'_, str> {
|
|||
let name = caps.name("name").unwrap().as_str();
|
||||
std::env::var(name).unwrap_or_else(|_| match name {
|
||||
// Ensure that the variable is URL-escaped, if necessary.
|
||||
"PROJECT_ROOT" => {
|
||||
if escape {
|
||||
PROJECT_ROOT_FRAGMENT.replace(' ', "%20")
|
||||
} else {
|
||||
PROJECT_ROOT_FRAGMENT.to_string()
|
||||
}
|
||||
}
|
||||
"PROJECT_ROOT" => match escape {
|
||||
Escape::Url => PROJECT_ROOT_FRAGMENT.replace(' ', "%20"),
|
||||
Escape::Path => PROJECT_ROOT_FRAGMENT.to_string(),
|
||||
},
|
||||
_ => caps["var"].to_owned(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Expand all available environment variables in a path-like string.
|
||||
pub fn expand_path_vars(path: &str) -> Cow<'_, str> {
|
||||
expand_env_vars(path, Escape::Path)
|
||||
}
|
||||
|
||||
/// Like [`Url::parse`], but only splits the scheme. Derived from the `url` crate.
|
||||
pub fn split_scheme(s: &str) -> Option<(&str, &str)> {
|
||||
/// <https://url.spec.whatwg.org/#c0-controls-and-space>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue