mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Allow non-file:// paths to serve as --index-url
values (#4524)
## Summary pip allows these with the following logic: ```python if os.path.exists(location): # Is a local path. url = path_to_url(location) path = location elif location.startswith("file:"): # A file: URL. url = location path = url_to_path(location) elif is_url(location): url = location ``` Closes https://github.com/astral-sh/uv/issues/4510. ## Test Plan `cargo run pip install --index-url ../packse/index/simple-html/ example-a-961b4c22 --reinstall --no-cache --no-deps`
This commit is contained in:
parent
3379e4c8c2
commit
e39f5f72fe
1 changed files with 33 additions and 10 deletions
|
@ -1,14 +1,15 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use url::Url;
|
use thiserror::Error;
|
||||||
|
use url::{ParseError, Url};
|
||||||
|
|
||||||
use pep508_rs::{expand_env_vars, split_scheme, strip_host, Scheme, VerbatimUrl};
|
use pep508_rs::{expand_env_vars, split_scheme, strip_host, Scheme, VerbatimUrl, VerbatimUrlError};
|
||||||
use uv_fs::normalize_url_path;
|
use uv_fs::normalize_url_path;
|
||||||
|
|
||||||
use crate::Verbatim;
|
use crate::Verbatim;
|
||||||
|
@ -90,18 +91,40 @@ impl Verbatim for IndexUrl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error that can occur when parsing an [`IndexUrl`].
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum IndexUrlError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Url(#[from] ParseError),
|
||||||
|
#[error(transparent)]
|
||||||
|
VerbatimUrl(#[from] VerbatimUrlError),
|
||||||
|
#[error("Index URL must be a valid base URL")]
|
||||||
|
CannotBeABase,
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for IndexUrl {
|
impl FromStr for IndexUrl {
|
||||||
type Err = url::ParseError;
|
type Err = IndexUrlError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let url = Url::parse(s)?;
|
if let Ok(path) = Path::new(s).canonicalize() {
|
||||||
let url = VerbatimUrl::from_url(url).with_given(s.to_owned());
|
let url = VerbatimUrl::from_path(path)?.with_given(s.to_owned());
|
||||||
if *url.raw() == *PYPI_URL {
|
|
||||||
Ok(Self::Pypi(url))
|
|
||||||
} else if url.scheme() == "file" {
|
|
||||||
Ok(Self::Path(url))
|
Ok(Self::Path(url))
|
||||||
} else {
|
} else {
|
||||||
Ok(Self::Url(url))
|
let url = Url::parse(s)?;
|
||||||
|
if url.cannot_be_a_base() {
|
||||||
|
Err(IndexUrlError::CannotBeABase)
|
||||||
|
} else {
|
||||||
|
let url = VerbatimUrl::from_url(url).with_given(s.to_owned());
|
||||||
|
if *url.raw() == *PYPI_URL {
|
||||||
|
Ok(Self::Pypi(url))
|
||||||
|
} else if url.scheme() == "file" {
|
||||||
|
Ok(Self::Path(url))
|
||||||
|
} else {
|
||||||
|
Ok(Self::Url(url))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue