Skip to content

Commit

Permalink
Allow non-file:// paths to serve as --index-url values (#4524)
Browse files Browse the repository at this point in the history
## 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 #4510.

## Test Plan

`cargo run pip install --index-url ../packse/index/simple-html/
example-a-961b4c22 --reinstall --no-cache --no-deps`
  • Loading branch information
charliermarsh authored Jun 25, 2024
1 parent 3379e4c commit e39f5f7
Showing 1 changed file with 33 additions and 10 deletions.
43 changes: 33 additions & 10 deletions crates/distribution-types/src/index_url.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::borrow::Cow;
use std::fmt::{Display, Formatter};
use std::ops::Deref;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::str::FromStr;

use itertools::Either;
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 crate::Verbatim;
Expand Down Expand Up @@ -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 {
type Err = url::ParseError;
type Err = IndexUrlError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let url = Url::parse(s)?;
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" {
if let Ok(path) = Path::new(s).canonicalize() {
let url = VerbatimUrl::from_path(path)?.with_given(s.to_owned());
Ok(Self::Path(url))
} 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))
}
}
}
}
}
Expand Down

0 comments on commit e39f5f7

Please sign in to comment.