mirror of https://github.com/astral-sh/uv
Deduplicate fetched index URLs (#13205)
<!-- Thank you for contributing to uv! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> Fixes #11970. ## Test Plan <!-- How was it tested? --> Ran `cargo nextest`
This commit is contained in:
parent
4c63c9c6a2
commit
801fd0e5b8
|
|
@ -489,9 +489,11 @@ impl<'a> IndexUrls {
|
||||||
/// If `no_index` was enabled, then this always returns an empty
|
/// If `no_index` was enabled, then this always returns an empty
|
||||||
/// iterator.
|
/// iterator.
|
||||||
pub fn indexes(&'a self) -> impl Iterator<Item = &'a Index> + 'a {
|
pub fn indexes(&'a self) -> impl Iterator<Item = &'a Index> + 'a {
|
||||||
|
let mut seen = FxHashSet::default();
|
||||||
self.implicit_indexes()
|
self.implicit_indexes()
|
||||||
.chain(self.default_index())
|
.chain(self.default_index())
|
||||||
.filter(|index| !index.explicit)
|
.filter(|index| !index.explicit)
|
||||||
|
.filter(move |index| seen.insert(index.raw_url())) // Filter out redundant raw URLs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an iterator over all user-defined [`Index`] entries in order.
|
/// Return an iterator over all user-defined [`Index`] entries in order.
|
||||||
|
|
|
||||||
|
|
@ -1878,6 +1878,43 @@ fn install_extra_index_url_has_priority() {
|
||||||
context.assert_command("import flask").failure();
|
context.assert_command("import flask").failure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensure that the index is fetched only once when duplicate indices are specified
|
||||||
|
#[tokio::test]
|
||||||
|
async fn install_deduplicated_indices() {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let redirect_server = MockServer::start().await;
|
||||||
|
|
||||||
|
Mock::given(method("GET"))
|
||||||
|
.respond_with(
|
||||||
|
ResponseTemplate::new(302).insert_header("Location", "https://pypi.org/simple/sniffio"),
|
||||||
|
)
|
||||||
|
.expect(1)
|
||||||
|
.mount(&redirect_server)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
uv_snapshot!(context
|
||||||
|
.pip_install()
|
||||||
|
.arg("sniffio") // Use a zero-dependency package
|
||||||
|
.arg("--index")
|
||||||
|
.arg(redirect_server.uri())
|
||||||
|
.arg("--default-index")
|
||||||
|
.arg(redirect_server.uri())
|
||||||
|
.arg("--index-strategy")
|
||||||
|
.arg("unsafe-first-match"), // Anything but "first-index"
|
||||||
|
@r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 1 package in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
+ sniffio==1.3.1
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
/// Install a package from a public GitHub repository
|
/// Install a package from a public GitHub repository
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue