Skip to content

Commit b4913eb

Browse files
committed
Avoid treating non-existent --find-links as relative URLs
1 parent 00a4adf commit b4913eb

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

crates/uv-client/src/flat_index.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,12 @@ impl<'a> FlatIndexClient<'a> {
243243
path: &Path,
244244
flat_index: &IndexUrl,
245245
) -> Result<FlatIndexEntries, FindLinksDirectoryError> {
246+
// The path context is provided by the caller.
247+
#[allow(clippy::disallowed_methods)]
248+
let entries = std::fs::read_dir(path)?;
249+
246250
let mut dists = Vec::new();
247-
for entry in fs_err::read_dir(path)? {
251+
for entry in entries {
248252
let entry = entry?;
249253
let metadata = entry.metadata()?;
250254

crates/uv-distribution-types/src/index_url.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
use itertools::Either;
2-
use rustc_hash::{FxHashMap, FxHashSet};
31
use std::borrow::Cow;
42
use std::fmt::{Display, Formatter};
53
use std::ops::Deref;
6-
use std::path::Path;
74
use std::str::FromStr;
85
use std::sync::{Arc, LazyLock, RwLock};
6+
7+
use itertools::Either;
8+
use rustc_hash::{FxHashMap, FxHashSet};
99
use thiserror::Error;
1010
use url::{ParseError, Url};
1111

12-
use uv_pep508::{VerbatimUrl, VerbatimUrlError};
12+
use uv_pep508::{split_scheme, Scheme, VerbatimUrl, VerbatimUrlError};
1313

1414
use crate::{Index, Verbatim};
1515

@@ -114,10 +114,23 @@ impl FromStr for IndexUrl {
114114
type Err = IndexUrlError;
115115

116116
fn from_str(s: &str) -> Result<Self, Self::Err> {
117-
let url = if Path::new(s).exists() {
118-
VerbatimUrl::from_absolute_path(std::path::absolute(s)?)?
119-
} else {
120-
VerbatimUrl::parse_url(s)?
117+
let url = match split_scheme(s) {
118+
Some((scheme, ..)) => {
119+
match Scheme::parse(scheme) {
120+
Some(_) => {
121+
// Ex) `https://pypi.org/simple`
122+
VerbatimUrl::parse_url(s)?
123+
}
124+
None => {
125+
// Ex) `C:\Users\user\index`
126+
VerbatimUrl::from_absolute_path(std::path::absolute(s)?)?
127+
}
128+
}
129+
}
130+
None => {
131+
// Ex) `/Users/user/index`
132+
VerbatimUrl::from_absolute_path(std::path::absolute(s)?)?
133+
}
121134
};
122135
Ok(Self::from(url.with_given(s)))
123136
}

crates/uv/tests/it/pip_install.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,41 @@ fn missing_pyproject_toml() {
7979
);
8080
}
8181

82+
#[test]
83+
fn missing_find_links() -> Result<()> {
84+
let context = TestContext::new("3.12");
85+
let requirements_txt = context.temp_dir.child("requirements.txt");
86+
requirements_txt.write_str("flask")?;
87+
88+
let error = regex::escape("The system cannot find the path specified. (os error 3)");
89+
let filters = context
90+
.filters()
91+
.into_iter()
92+
.chain(std::iter::once((
93+
error.as_str(),
94+
"No such file or directory (os error 2)",
95+
)))
96+
.collect::<Vec<_>>();
97+
98+
uv_snapshot!(filters, context.pip_install()
99+
.arg("-r")
100+
.arg("requirements.txt")
101+
.arg("--find-links")
102+
.arg("./missing")
103+
.arg("--strict"), @r###"
104+
success: false
105+
exit_code: 2
106+
----- stdout -----
107+
108+
----- stderr -----
109+
error: Failed to read `--find-links` directory: [TEMP_DIR]/missing
110+
Caused by: No such file or directory (os error 2)
111+
"###
112+
);
113+
114+
Ok(())
115+
}
116+
82117
#[test]
83118
fn invalid_pyproject_toml_syntax() -> Result<()> {
84119
let context = TestContext::new("3.12");

0 commit comments

Comments
 (0)