From 822ae19879ea4f1e49562f3468985b8b240e0268 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Thu, 18 Apr 2024 19:48:21 -0500 Subject: [PATCH] Restore seeding of authentication cache from index URLs (#3124) Roughly reverts https://github.com/astral-sh/uv/pull/2976/commits/f7820ceaa7a24613ce89da77c48a0454c1e94616 to reduce possible race conditions for pre-authenticated index URLs Part of: - https://github.com/astral-sh/uv/issues/3123 - https://github.com/astral-sh/uv/issues/3122 --- crates/uv-auth/src/lib.rs | 16 ++++++++++++++++ crates/uv/src/commands/pip_compile.rs | 6 ++++++ crates/uv/src/commands/pip_install.rs | 6 ++++++ crates/uv/src/commands/pip_sync.rs | 6 ++++++ crates/uv/src/commands/venv.rs | 6 ++++++ 5 files changed, 40 insertions(+) diff --git a/crates/uv-auth/src/lib.rs b/crates/uv-auth/src/lib.rs index 81fd0aeb85f4..ce564074d466 100644 --- a/crates/uv-auth/src/lib.rs +++ b/crates/uv-auth/src/lib.rs @@ -4,12 +4,16 @@ mod keyring; mod middleware; mod netloc; +use std::sync::Arc; + use cache::CredentialsCache; +use credentials::Credentials; pub use keyring::KeyringProvider; pub use middleware::AuthMiddleware; use netloc::NetLoc; use once_cell::sync::Lazy; +use url::Url; // TODO(zanieb): Consider passing a cache explicitly throughout @@ -17,3 +21,15 @@ use once_cell::sync::Lazy; /// /// This is used to share credentials across uv clients. pub(crate) static CREDENTIALS_CACHE: Lazy = Lazy::new(CredentialsCache::default); + +/// Populate the global authentication store with credentials on a URL, if there are any. +/// +/// Returns `true` if the store was updated. +pub fn store_credentials_from_url(url: &Url) -> bool { + if let Some(credentials) = Credentials::from_url(url) { + CREDENTIALS_CACHE.insert(url, Arc::new(credentials)); + true + } else { + false + } +} diff --git a/crates/uv/src/commands/pip_compile.rs b/crates/uv/src/commands/pip_compile.rs index 006e80b04c58..c35d216a38a1 100644 --- a/crates/uv/src/commands/pip_compile.rs +++ b/crates/uv/src/commands/pip_compile.rs @@ -17,6 +17,7 @@ use distribution_types::{IndexLocations, LocalEditable, LocalEditables, Verbatim use install_wheel_rs::linker::LinkMode; use platform_tags::Tags; use requirements_txt::EditableRequirement; +use uv_auth::store_credentials_from_url; use uv_cache::Cache; use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder}; use uv_configuration::KeyringProviderType; @@ -219,6 +220,11 @@ pub(crate) async fn pip_compile( let index_locations = index_locations.combine(index_url, extra_index_urls, find_links, no_index); + // Add all authenticated sources to the cache. + for url in index_locations.urls() { + store_credentials_from_url(url); + } + // Initialize the registry client. let client = RegistryClientBuilder::new(cache.clone()) .native_tls(native_tls) diff --git a/crates/uv/src/commands/pip_install.rs b/crates/uv/src/commands/pip_install.rs index c26477324f16..22d71a671f61 100644 --- a/crates/uv/src/commands/pip_install.rs +++ b/crates/uv/src/commands/pip_install.rs @@ -19,6 +19,7 @@ use pep508_rs::{MarkerEnvironment, Requirement}; use platform_tags::Tags; use pypi_types::{Metadata23, Yanked}; use requirements_txt::EditableRequirement; +use uv_auth::store_credentials_from_url; use uv_cache::Cache; use uv_client::{ BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClient, RegistryClientBuilder, @@ -203,6 +204,11 @@ pub(crate) async fn pip_install( let index_locations = index_locations.combine(index_url, extra_index_urls, find_links, no_index); + // Add all authenticated sources to the cache. + for url in index_locations.urls() { + store_credentials_from_url(url); + } + // Initialize the registry client. let client = RegistryClientBuilder::new(cache.clone()) .native_tls(native_tls) diff --git a/crates/uv/src/commands/pip_sync.rs b/crates/uv/src/commands/pip_sync.rs index a532f5473ed2..764f308ec52a 100644 --- a/crates/uv/src/commands/pip_sync.rs +++ b/crates/uv/src/commands/pip_sync.rs @@ -14,6 +14,7 @@ use install_wheel_rs::linker::LinkMode; use platform_tags::Tags; use pypi_types::Yanked; use requirements_txt::EditableRequirement; +use uv_auth::store_credentials_from_url; use uv_cache::{ArchiveTarget, ArchiveTimestamp, Cache}; use uv_client::{ BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClient, RegistryClientBuilder, @@ -150,6 +151,11 @@ pub(crate) async fn pip_sync( let index_locations = index_locations.combine(index_url, extra_index_urls, find_links, no_index); + // Add all authenticated sources to the cache. + for url in index_locations.urls() { + store_credentials_from_url(url); + } + // Initialize the registry client. let client = RegistryClientBuilder::new(cache.clone()) .native_tls(native_tls) diff --git a/crates/uv/src/commands/venv.rs b/crates/uv/src/commands/venv.rs index 521d80f14cff..cadbf49328fc 100644 --- a/crates/uv/src/commands/venv.rs +++ b/crates/uv/src/commands/venv.rs @@ -14,6 +14,7 @@ use thiserror::Error; use distribution_types::{DistributionMetadata, IndexLocations, Name, ResolvedDist}; use install_wheel_rs::linker::LinkMode; use pep508_rs::Requirement; +use uv_auth::store_credentials_from_url; use uv_cache::Cache; use uv_client::{Connectivity, FlatIndexClient, RegistryClientBuilder}; use uv_configuration::KeyringProviderType; @@ -119,6 +120,11 @@ async fn venv_impl( find_default_python(cache).into_diagnostic()? }; + // Add all authenticated sources to the cache. + for url in index_locations.urls() { + store_credentials_from_url(url); + } + writeln!( printer.stderr(), "Using Python {} interpreter at: {}",