Skip to content

Commit

Permalink
Use lazy_static for memoization
Browse files Browse the repository at this point in the history
  • Loading branch information
BakerNet committed Mar 7, 2024
1 parent c7ee0b0 commit 0294317
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 15 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ indicatif = { version = "0.17.7" }
indoc = { version = "2.0.4" }
itertools = { version = "0.12.1" }
junction = { version = "1.0.0" }
lazy_static = { version = "1.4.0" }
mailparse = { version = "0.14.0" }
miette = { version = "6.0.0" }
nanoid = { version = "0.4.0" }
Expand Down
11 changes: 8 additions & 3 deletions crates/uv-client/src/middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ impl RequestInitialiser for KeyringMiddleware {
.unwrap()
.build()
.ok()
.map(|r| {
let auth = get_keyring_auth(r.url()).unwrap_or_else(|e| panic!("{}", e));
nr.basic_auth(auth.username, Some(auth.password))
.and_then(|r| {
let url = r.url();
match get_keyring_auth(url) {
Ok(auth) => {
Some(nr.basic_auth(auth.username.clone(), Some(auth.password.clone())))
}
_ => None,
}
})
.unwrap_or(req),
None => req,
Expand Down
3 changes: 2 additions & 1 deletion crates/uv-client/src/registry_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ impl RegistryClientBuilder {
};

// Initialize keyring middleware.
// Note - this will overwrite netrc middleware if both are used
// Note - this will overwrite netrc middleware if both are used and a
// keyring password exists
let client = if self.use_keyring {
client.with_init(KeyringMiddleware)
} else {
Expand Down
1 change: 1 addition & 0 deletions crates/uv-keyring/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ workspace = true

[dependencies]
anyhow = { workspace = true }
lazy_static = { workspace = true }
tracing = { workspace = true }
url = { workspace = true }
45 changes: 34 additions & 11 deletions crates/uv-keyring/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
use std::process::Command;
use lazy_static::lazy_static;
use std::{collections::HashMap, process::Command, sync::Mutex};

use anyhow::{bail, Result};
use anyhow::{anyhow, bail, Result};
use tracing::debug;
use url::Url;

lazy_static! {
static ref PASSWORDS: Mutex<HashMap<String, Option<BasicAuthData>>> =
Mutex::new(HashMap::new());
}

#[derive(Clone, Debug, PartialEq)]
pub struct BasicAuthData {
pub username: String,
pub password: String,
}

pub fn get_keyring_auth(url: &Url) -> Result<BasicAuthData> {
let host = url.host_str();
if host.is_none() {
bail!("Should only use keyring for urls with host");
}
let host = host.unwrap();
if url.password().is_some() {
bail!("Url already contains password - keyring not required")
}
let mut passwords = PASSWORDS.lock().unwrap();
if passwords.contains_key(host) {
return passwords
.get(host)
.unwrap()
.clone()
.ok_or(anyhow!("Previously failed to find keyring password"));
}
let username = match url.username() {
u if !u.is_empty() => u,
// this is the username keyring.get_credentials returns as username for GCP registry
_ => "oauth2accesstoken",
};
debug!(
Expand All @@ -29,20 +49,23 @@ pub fn get_keyring_auth(url: &Url) -> Result<BasicAuthData> {
.arg(username)
.output()
{
Ok(output) if output.status.success() => {
String::from_utf8(output.stdout).expect("Keyring output should be valid utf8")
}
Ok(output) => bail!(
Ok(output) if output.status.success() => Ok(String::from_utf8(output.stdout)
.expect("Keyring output should be valid utf8")
.trim_end()
.to_owned()),
Ok(output) => Err(anyhow!(
"Unable to get keyring password for {url}: {}",
String::from_utf8(output.stderr)
.unwrap_or(String::from("Unable to convert stderr to String")),
),
Err(e) => bail!(e),
)),
Err(e) => Err(anyhow!(e)),
};
Ok(BasicAuthData {
let output = output.map(|password| BasicAuthData {
username: username.to_string(),
password: output,
})
password,
});
passwords.insert(host.to_string(), output.as_ref().ok().cloned());
output
}

#[cfg(test)]
Expand Down

0 comments on commit 0294317

Please sign in to comment.