Skip to content

Commit 1dfa650

Browse files
authored
Propagate credentials for <index>/simple to <index>/... endpoints (#11074)
Closes #11017 Closes #8565 Sort of an minimal implementation of #4583
1 parent d281f49 commit 1dfa650

File tree

12 files changed

+103
-24
lines changed

12 files changed

+103
-24
lines changed

crates/uv-auth/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn store_credentials_from_url(url: &Url) -> bool {
3939
/// Populate the global authentication store with credentials on a URL, if there are any.
4040
///
4141
/// Returns `true` if the store was updated.
42-
pub fn store_credentials(url: &Url, credentials: Credentials) {
42+
pub fn store_credentials(url: &Url, credentials: Arc<Credentials>) {
4343
trace!("Caching credentials for {url}");
44-
CREDENTIALS_CACHE.insert(url, Arc::new(credentials));
44+
CREDENTIALS_CACHE.insert(url, credentials);
4545
}

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,27 @@ impl Index {
150150
self.url
151151
}
152152

153-
/// Return the raw [`URL`] of the index.
153+
/// Return the raw [`Url`] of the index.
154154
pub fn raw_url(&self) -> &Url {
155155
self.url.url()
156156
}
157157

158+
/// Return the root [`Url`] of the index, if applicable.
159+
///
160+
/// For indexes with a `/simple` endpoint, this is simply the URL with the final segment
161+
/// removed. This is useful, e.g., for credential propagation to other endpoints on the index.
162+
pub fn root_url(&self) -> Option<Url> {
163+
let segments = self.raw_url().path_segments()?;
164+
let last = segments.last()?;
165+
if !last.eq_ignore_ascii_case("simple") {
166+
return None;
167+
}
168+
169+
let mut url = self.raw_url().clone();
170+
url.path_segments_mut().ok()?.pop();
171+
Some(url)
172+
}
173+
158174
/// Retrieve the credentials for the index, either from the environment, or from the URL itself.
159175
pub fn credentials(&self) -> Option<Credentials> {
160176
// If the index is named, and credentials are provided via the environment, prefer those.

crates/uv/src/commands/build_frontend.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::fmt::Write as _;
33
use std::io::Write as _;
44
use std::path::{Path, PathBuf};
55
use std::str::FromStr;
6+
use std::sync::Arc;
67
use std::{fmt, io};
78

89
use anyhow::{Context, Result};
@@ -16,7 +17,6 @@ use crate::commands::reporters::PythonDownloadReporter;
1617
use crate::commands::ExitStatus;
1718
use crate::printer::Printer;
1819
use crate::settings::{ResolverSettings, ResolverSettingsRef};
19-
use uv_auth::store_credentials;
2020
use uv_build_backend::check_direct_build;
2121
use uv_cache::{Cache, CacheBucket};
2222
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
@@ -496,7 +496,11 @@ async fn build_package(
496496
// Add all authenticated sources to the cache.
497497
for index in index_locations.allowed_indexes() {
498498
if let Some(credentials) = index.credentials() {
499-
store_credentials(index.raw_url(), credentials);
499+
let credentials = Arc::new(credentials);
500+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
501+
if let Some(root_url) = index.root_url() {
502+
uv_auth::store_credentials(&root_url, credentials.clone());
503+
}
500504
}
501505
}
502506

crates/uv/src/commands/pip/compile.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::collections::BTreeSet;
22
use std::env;
33
use std::path::Path;
4+
use std::sync::Arc;
45

56
use anyhow::{anyhow, Result};
67
use itertools::Itertools;
@@ -292,7 +293,11 @@ pub(crate) async fn pip_compile(
292293
// Add all authenticated sources to the cache.
293294
for index in index_locations.allowed_indexes() {
294295
if let Some(credentials) = index.credentials() {
295-
uv_auth::store_credentials(index.raw_url(), credentials);
296+
let credentials = Arc::new(credentials);
297+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
298+
if let Some(root_url) = index.root_url() {
299+
uv_auth::store_credentials(&root_url, credentials.clone());
300+
}
296301
}
297302
}
298303

crates/uv/src/commands/pip/install.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::BTreeSet;
22
use std::fmt::Write;
3+
use std::sync::Arc;
34

45
use itertools::Itertools;
56
use owo_colors::OwoColorize;
@@ -311,7 +312,11 @@ pub(crate) async fn pip_install(
311312
// Add all authenticated sources to the cache.
312313
for index in index_locations.allowed_indexes() {
313314
if let Some(credentials) = index.credentials() {
314-
uv_auth::store_credentials(index.raw_url(), credentials);
315+
let credentials = Arc::new(credentials);
316+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
317+
if let Some(root_url) = index.root_url() {
318+
uv_auth::store_credentials(&root_url, credentials.clone());
319+
}
315320
}
316321
}
317322

crates/uv/src/commands/pip/sync.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::BTreeSet;
22
use std::fmt::Write;
3+
use std::sync::Arc;
34

45
use anyhow::Result;
56
use owo_colors::OwoColorize;
@@ -251,7 +252,11 @@ pub(crate) async fn pip_sync(
251252
// Add all authenticated sources to the cache.
252253
for index in index_locations.allowed_indexes() {
253254
if let Some(credentials) = index.credentials() {
254-
uv_auth::store_credentials(index.raw_url(), credentials);
255+
let credentials = Arc::new(credentials);
256+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
257+
if let Some(root_url) = index.root_url() {
258+
uv_auth::store_credentials(&root_url, credentials.clone());
259+
}
255260
}
256261
}
257262

crates/uv/src/commands/project/add.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,11 @@ pub(crate) async fn add(
286286
// Add all authenticated sources to the cache.
287287
for index in settings.index_locations.allowed_indexes() {
288288
if let Some(credentials) = index.credentials() {
289-
uv_auth::store_credentials(index.raw_url(), credentials);
289+
let credentials = Arc::new(credentials);
290+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
291+
if let Some(root_url) = index.root_url() {
292+
uv_auth::store_credentials(&root_url, credentials.clone());
293+
}
290294
}
291295
}
292296

crates/uv/src/commands/project/lock.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,13 +466,21 @@ async fn do_lock(
466466
// Add all authenticated sources to the cache.
467467
for index in index_locations.allowed_indexes() {
468468
if let Some(credentials) = index.credentials() {
469-
uv_auth::store_credentials(index.raw_url(), credentials);
469+
let credentials = Arc::new(credentials);
470+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
471+
if let Some(root_url) = index.root_url() {
472+
uv_auth::store_credentials(&root_url, credentials.clone());
473+
}
470474
}
471475
}
472476

473477
for index in target.indexes() {
474478
if let Some(credentials) = index.credentials() {
475-
uv_auth::store_credentials(index.raw_url(), credentials);
479+
let credentials = Arc::new(credentials);
480+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
481+
if let Some(root_url) = index.root_url() {
482+
uv_auth::store_credentials(&root_url, credentials.clone());
483+
}
476484
}
477485
}
478486

crates/uv/src/commands/project/mod.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,11 @@ pub(crate) async fn resolve_names(
10781078
// Add all authenticated sources to the cache.
10791079
for index in index_locations.allowed_indexes() {
10801080
if let Some(credentials) = index.credentials() {
1081-
uv_auth::store_credentials(index.raw_url(), credentials);
1081+
let credentials = Arc::new(credentials);
1082+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
1083+
if let Some(root_url) = index.root_url() {
1084+
uv_auth::store_credentials(&root_url, credentials.clone());
1085+
}
10821086
}
10831087
}
10841088

@@ -1228,7 +1232,11 @@ pub(crate) async fn resolve_environment(
12281232
// Add all authenticated sources to the cache.
12291233
for index in index_locations.allowed_indexes() {
12301234
if let Some(credentials) = index.credentials() {
1231-
uv_auth::store_credentials(index.raw_url(), credentials);
1235+
let credentials = Arc::new(credentials);
1236+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
1237+
if let Some(root_url) = index.root_url() {
1238+
uv_auth::store_credentials(&root_url, credentials.clone());
1239+
}
12321240
}
12331241
}
12341242

@@ -1395,7 +1403,11 @@ pub(crate) async fn sync_environment(
13951403
// Add all authenticated sources to the cache.
13961404
for index in index_locations.allowed_indexes() {
13971405
if let Some(credentials) = index.credentials() {
1398-
uv_auth::store_credentials(index.raw_url(), credentials);
1406+
let credentials = Arc::new(credentials);
1407+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
1408+
if let Some(root_url) = index.root_url() {
1409+
uv_auth::store_credentials(&root_url, credentials.clone());
1410+
}
13991411
}
14001412
}
14011413

@@ -1590,7 +1602,11 @@ pub(crate) async fn update_environment(
15901602
// Add all authenticated sources to the cache.
15911603
for index in index_locations.allowed_indexes() {
15921604
if let Some(credentials) = index.credentials() {
1593-
uv_auth::store_credentials(index.raw_url(), credentials);
1605+
let credentials = Arc::new(credentials);
1606+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
1607+
if let Some(root_url) = index.root_url() {
1608+
uv_auth::store_credentials(&root_url, credentials.clone());
1609+
}
15941610
}
15951611
}
15961612

crates/uv/src/commands/project/sync.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use std::path::Path;
2+
use std::sync::Arc;
23

34
use anyhow::{Context, Result};
45
use itertools::Itertools;
56

6-
use uv_auth::store_credentials;
77
use uv_cache::Cache;
88
use uv_client::{Connectivity, FlatIndexClient, RegistryClientBuilder};
99
use uv_configuration::{
@@ -353,7 +353,11 @@ pub(super) async fn do_sync(
353353
// Add all authenticated sources to the cache.
354354
for index in index_locations.allowed_indexes() {
355355
if let Some(credentials) = index.credentials() {
356-
store_credentials(index.raw_url(), credentials);
356+
let credentials = Arc::new(credentials);
357+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
358+
if let Some(root_url) = index.root_url() {
359+
uv_auth::store_credentials(&root_url, credentials.clone());
360+
}
357361
}
358362
}
359363

@@ -520,7 +524,11 @@ fn store_credentials_from_target(target: InstallTarget<'_>) {
520524
// Iterate over any idnexes in the target.
521525
for index in target.indexes() {
522526
if let Some(credentials) = index.credentials() {
523-
store_credentials(index.raw_url(), credentials);
527+
let credentials = Arc::new(credentials);
528+
uv_auth::store_credentials(index.raw_url(), credentials.clone());
529+
if let Some(root_url) = index.root_url() {
530+
uv_auth::store_credentials(&root_url, credentials.clone());
531+
}
524532
}
525533
}
526534

0 commit comments

Comments
 (0)