Respect `UV_CREDENTIALS_DIR` (#15598)

This commit is contained in:
Zanie Blue 2025-08-30 12:27:13 -05:00
parent 4d79fd2c04
commit a13fb3ec64
6 changed files with 36 additions and 16 deletions

2
Cargo.lock generated
View File

@ -5095,11 +5095,11 @@ dependencies = [
"toml", "toml",
"tracing", "tracing",
"url", "url",
"uv-dirs",
"uv-keyring", "uv-keyring",
"uv-once-map", "uv-once-map",
"uv-redacted", "uv-redacted",
"uv-small-str", "uv-small-str",
"uv-state",
"uv-static", "uv-static",
"uv-warnings", "uv-warnings",
"wiremock", "wiremock",

View File

@ -10,12 +10,12 @@ doctest = false
workspace = true workspace = true
[dependencies] [dependencies]
uv-dirs = { workspace = true }
uv-keyring = { workspace = true, features = ["apple-native", "secret-service", "windows-native"] } uv-keyring = { workspace = true, features = ["apple-native", "secret-service", "windows-native"] }
uv-once-map = { workspace = true } uv-once-map = { workspace = true }
uv-redacted = { workspace = true } uv-redacted = { workspace = true }
uv-small-str = { workspace = true } uv-small-str = { workspace = true }
uv-static = { workspace = true } uv-static = { workspace = true }
uv-state = { workspace = true }
uv-warnings = { workspace = true } uv-warnings = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }

View File

@ -65,25 +65,25 @@ impl Default for TextStoreMode {
// TODO(zanieb): Reconsider this pattern. We're just mirroring the [`NetrcMode`] // TODO(zanieb): Reconsider this pattern. We're just mirroring the [`NetrcMode`]
// implementation for now. // implementation for now.
Self::Automatic(LazyLock::new(|| { Self::Automatic(LazyLock::new(|| {
let state_dir = uv_dirs::user_state_dir()?; let path = TextCredentialStore::default_file()
let credentials_path = state_dir.join("credentials").join("credentials.toml"); .inspect_err(|err| {
warn!("Failed to determine credentials file path: {}", err);
})
.ok()?;
match TextCredentialStore::from_file(&credentials_path) { match TextCredentialStore::from_file(&path) {
Ok(store) => { Ok(store) => {
debug!("Loaded credential file {}", credentials_path.display()); debug!("Loaded credential file {}", path.display());
Some(store) Some(store)
} }
Err(TomlCredentialError::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => { Err(TomlCredentialError::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
debug!( debug!("No credentials file found at {}", path.display());
"No credentials file found at {}",
credentials_path.display()
);
None None
} }
Err(err) => { Err(err) => {
warn!( warn!(
"Failed to load credentials from {}: {}", "Failed to load credentials from {}: {}",
credentials_path.display(), path.display(),
err err
); );
None None

View File

@ -9,6 +9,9 @@ use tracing::debug;
use url::Url; use url::Url;
use uv_redacted::DisplaySafeUrl; use uv_redacted::DisplaySafeUrl;
use uv_state::{StateBucket, StateStore};
use uv_static::EnvVars;
use crate::Credentials; use crate::Credentials;
use crate::credentials::{Password, Username}; use crate::credentials::{Password, Username};
use crate::realm::Realm; use crate::realm::Realm;
@ -182,12 +185,22 @@ pub struct TextCredentialStore {
} }
impl TextCredentialStore { impl TextCredentialStore {
/// Return the default credential file path. /// Return the directory for storing credentials.
fn directory_path() -> Result<PathBuf, TomlCredentialError> {
if let Some(dir) = std::env::var_os(EnvVars::UV_CREDENTIALS_DIR)
.filter(|s| !s.is_empty())
.map(PathBuf::from)
{
return Ok(dir);
}
Ok(StateStore::from_settings(None)?.bucket(StateBucket::Credentials))
}
/// Return the standard file path for storing credentials.
pub fn default_file() -> Result<PathBuf, TomlCredentialError> { pub fn default_file() -> Result<PathBuf, TomlCredentialError> {
let state_dir = let dir = Self::directory_path()?;
uv_dirs::user_state_dir().ok_or(TomlCredentialError::CredentialsDirError)?; Ok(dir.join("credentials.toml"))
let credentials_dir = state_dir.join("credentials");
Ok(credentials_dir.join("credentials.toml"))
} }
/// Read credentials from a file. /// Read credentials from a file.

View File

@ -45,6 +45,9 @@ impl EnvVars {
/// directory for caching instead of the default cache directory. /// directory for caching instead of the default cache directory.
pub const UV_CACHE_DIR: &'static str = "UV_CACHE_DIR"; pub const UV_CACHE_DIR: &'static str = "UV_CACHE_DIR";
/// The directory for storage of credentials when using a plain text backend.
pub const UV_CREDENTIALS_DIR: &'static str = "UV_CREDENTIALS_DIR";
/// Equivalent to the `--no-cache` command-line argument. If set, uv will not use the /// Equivalent to the `--no-cache` command-line argument. If set, uv will not use the
/// cache for any operations. /// cache for any operations.
pub const UV_NO_CACHE: &'static str = "UV_NO_CACHE"; pub const UV_NO_CACHE: &'static str = "UV_NO_CACHE";

View File

@ -55,6 +55,10 @@ local `uv.toml` file to use as the configuration file.
Equivalent to the `--constraint` command-line argument. If set, uv will use this Equivalent to the `--constraint` command-line argument. If set, uv will use this
file as the constraints file. Uses space-separated list of files. file as the constraints file. Uses space-separated list of files.
### `UV_CREDENTIALS_DIR`
The directory for storage of credentials when using a plain text backend.
### `UV_CUSTOM_COMPILE_COMMAND` ### `UV_CUSTOM_COMPILE_COMMAND`
Equivalent to the `--custom-compile-command` command-line argument. Equivalent to the `--custom-compile-command` command-line argument.