mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Display ssh git username in Debug
implementation (#13806)
This updates the `Debug` implementation of `DisplaySafeUrl` to display the git username in a case like `git+ssh://git@github.com/org/repo`. It also factors out the git username check into a shared function and adds related unit tests to `DisplaySafeUrl`.
This commit is contained in:
parent
a96e766b55
commit
90aefe4a4a
1 changed files with 52 additions and 18 deletions
|
@ -91,10 +91,7 @@ impl DisplaySafeUrl {
|
|||
pub fn remove_credentials(&mut self) {
|
||||
// For URLs that use the `git` convention (i.e., `ssh://git@github.com/...`), avoid dropping the
|
||||
// username.
|
||||
if matches!(self.0.scheme(), "git+ssh" | "ssh")
|
||||
&& self.0.username() == "git"
|
||||
&& self.0.password().is_none()
|
||||
{
|
||||
if is_ssh_git_username(&self.0) {
|
||||
return;
|
||||
}
|
||||
let _ = self.0.set_username("");
|
||||
|
@ -131,7 +128,11 @@ impl Display for DisplaySafeUrl {
|
|||
impl Debug for DisplaySafeUrl {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let url = &self.0;
|
||||
let (username, password) = if url.username() != "" && url.password().is_some() {
|
||||
// For URLs that use the `git` convention (i.e., `ssh://git@github.com/...`), avoid masking the
|
||||
// username.
|
||||
let (username, password) = if is_ssh_git_username(url) {
|
||||
(url.username(), None)
|
||||
} else if url.username() != "" && url.password().is_some() {
|
||||
(url.username(), Some("****"))
|
||||
} else if url.username() != "" {
|
||||
("****", None)
|
||||
|
@ -175,6 +176,10 @@ impl FromStr for DisplaySafeUrl {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_ssh_git_username(url: &Url) -> bool {
|
||||
matches!(url.scheme(), "ssh" | "git+ssh") && url.username() == "git" && url.password().is_none()
|
||||
}
|
||||
|
||||
fn display_with_redacted_credentials(
|
||||
url: &Url,
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
|
@ -185,10 +190,7 @@ fn display_with_redacted_credentials(
|
|||
|
||||
// For URLs that use the `git` convention (i.e., `ssh://git@github.com/...`), avoid dropping the
|
||||
// username.
|
||||
if matches!(url.scheme(), "git+ssh" | "ssh")
|
||||
&& url.username() == "git"
|
||||
&& url.password().is_none()
|
||||
{
|
||||
if is_ssh_git_username(url) {
|
||||
return write!(f, "{url}");
|
||||
}
|
||||
|
||||
|
@ -231,7 +233,7 @@ mod tests {
|
|||
let log_safe_url = DisplaySafeUrl::from(url);
|
||||
assert_eq!(log_safe_url.username(), "");
|
||||
assert!(log_safe_url.password().is_none());
|
||||
assert_eq!(format!("{log_safe_url}"), url_str);
|
||||
assert_eq!(log_safe_url.to_string(), url_str);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -242,7 +244,7 @@ mod tests {
|
|||
assert_eq!(log_safe_url.username(), "user");
|
||||
assert!(log_safe_url.password().is_some_and(|p| p == "pass"));
|
||||
assert_eq!(
|
||||
format!("{log_safe_url}"),
|
||||
log_safe_url.to_string(),
|
||||
"https://user:****@pypi-proxy.fly.dev/basic-auth/simple"
|
||||
);
|
||||
}
|
||||
|
@ -255,7 +257,7 @@ mod tests {
|
|||
assert_eq!(log_safe_url.username(), "");
|
||||
assert!(log_safe_url.password().is_some_and(|p| p == "pass"));
|
||||
assert_eq!(
|
||||
format!("{log_safe_url}"),
|
||||
log_safe_url.to_string(),
|
||||
"https://:****@pypi-proxy.fly.dev/basic-auth/simple"
|
||||
);
|
||||
}
|
||||
|
@ -268,11 +270,26 @@ mod tests {
|
|||
assert_eq!(log_safe_url.username(), "user");
|
||||
assert!(log_safe_url.password().is_none());
|
||||
assert_eq!(
|
||||
format!("{log_safe_url}"),
|
||||
log_safe_url.to_string(),
|
||||
"https://****@pypi-proxy.fly.dev/basic-auth/simple"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_url_git_username() {
|
||||
let ssh_str = "ssh://git@github.com/org/repo";
|
||||
let ssh_url = DisplaySafeUrl::parse(ssh_str).unwrap();
|
||||
assert_eq!(ssh_url.username(), "git");
|
||||
assert!(ssh_url.password().is_none());
|
||||
assert_eq!(ssh_url.to_string(), ssh_str);
|
||||
// Test again for the `git+ssh` scheme
|
||||
let git_ssh_str = "git+ssh://git@github.com/org/repo";
|
||||
let git_ssh_url = DisplaySafeUrl::parse(git_ssh_str).unwrap();
|
||||
assert_eq!(git_ssh_url.username(), "git");
|
||||
assert!(git_ssh_url.password().is_none());
|
||||
assert_eq!(git_ssh_url.to_string(), git_ssh_str);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_url_string() {
|
||||
let url_str = "https://user:pass@pypi-proxy.fly.dev/basic-auth/simple";
|
||||
|
@ -280,7 +297,7 @@ mod tests {
|
|||
assert_eq!(log_safe_url.username(), "user");
|
||||
assert!(log_safe_url.password().is_some_and(|p| p == "pass"));
|
||||
assert_eq!(
|
||||
format!("{log_safe_url}"),
|
||||
log_safe_url.to_string(),
|
||||
"https://user:****@pypi-proxy.fly.dev/basic-auth/simple"
|
||||
);
|
||||
}
|
||||
|
@ -293,17 +310,34 @@ mod tests {
|
|||
assert_eq!(log_safe_url.username(), "");
|
||||
assert!(log_safe_url.password().is_none());
|
||||
assert_eq!(
|
||||
format!("{log_safe_url}"),
|
||||
log_safe_url.to_string(),
|
||||
"https://pypi-proxy.fly.dev/basic-auth/simple"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preserve_ssh_git_username_on_remove_credentials() {
|
||||
let ssh_str = "ssh://git@pypi-proxy.fly.dev/basic-auth/simple";
|
||||
let mut ssh_url = DisplaySafeUrl::parse(ssh_str).unwrap();
|
||||
ssh_url.remove_credentials();
|
||||
assert_eq!(ssh_url.username(), "git");
|
||||
assert!(ssh_url.password().is_none());
|
||||
assert_eq!(ssh_url.to_string(), ssh_str);
|
||||
// Test again for `git+ssh` scheme
|
||||
let git_ssh_str = "git+ssh://git@pypi-proxy.fly.dev/basic-auth/simple";
|
||||
let mut git_shh_url = DisplaySafeUrl::parse(git_ssh_str).unwrap();
|
||||
git_shh_url.remove_credentials();
|
||||
assert_eq!(git_shh_url.username(), "git");
|
||||
assert!(git_shh_url.password().is_none());
|
||||
assert_eq!(git_shh_url.to_string(), git_ssh_str);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn displayable_with_credentials() {
|
||||
let url_str = "https://user:pass@pypi-proxy.fly.dev/basic-auth/simple";
|
||||
let log_safe_url = DisplaySafeUrl::parse(url_str).unwrap();
|
||||
assert_eq!(
|
||||
&log_safe_url.displayable_with_credentials().to_string(),
|
||||
log_safe_url.displayable_with_credentials().to_string(),
|
||||
url_str
|
||||
);
|
||||
}
|
||||
|
@ -313,7 +347,7 @@ mod tests {
|
|||
let url_str = "https://token@example.com/abc/";
|
||||
let log_safe_url = DisplaySafeUrl::parse(url_str).unwrap();
|
||||
let foo_url = log_safe_url.join("foo").unwrap();
|
||||
assert_eq!(format!("{foo_url}"), "https://****@example.com/abc/foo");
|
||||
assert_eq!(foo_url.to_string(), "https://****@example.com/abc/foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -324,7 +358,7 @@ mod tests {
|
|||
assert_eq!(log_safe_url.username(), "user");
|
||||
assert!(log_safe_url.password().is_some_and(|p| p == "pass"));
|
||||
assert_eq!(
|
||||
format!("{log_safe_url}"),
|
||||
log_safe_url.to_string(),
|
||||
"https://user:****@pypi-proxy.fly.dev/basic-auth/simple"
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue