use std::path::Path;
use auth_git2::Prompter;
use inquire::{InquireError, PasswordDisplayMode};
use crate::Config;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Inquirer<'a>(pub &'a Config);
fn config_value(git_config: &git2::Config, name: &str) -> Option<String> {
git_config
.get_entry(name)
.ok()
.and_then(|entry| entry.value().map(|entry| entry.to_string()))
}
fn prompt_secret(message: &str) -> Result<String, InquireError> {
inquire::Password::new(message)
.without_confirmation()
.with_display_mode(PasswordDisplayMode::Masked)
.prompt()
}
impl Prompter for Inquirer<'_> {
fn prompt_username_password(
&mut self,
url: &str,
git_config: &git2::Config,
) -> Option<(String, String)> {
let username = self
.0
.username_for_url(url)
.cloned()
.or_else(|| config_value(git_config, "autosave.username"));
let password = self
.0
.password_for_url(url)
.cloned()
.or_else(|| config_value(git_config, "autosave.password"));
if let Some(username) = username
&& let Some(password) = password
{
return Some((username, password));
}
println!("Authenticating to {url}");
let username = inquire::prompt_text("Username:").ok()?;
let password = prompt_secret("Password:").ok()?;
Some((username, password))
}
fn prompt_password(
&mut self,
username: &str,
url: &str,
git_config: &git2::Config,
) -> Option<String> {
let password = self
.0
.password_for_url(url)
.cloned()
.or_else(|| config_value(git_config, "autosave.password"));
if let Some(password) = password {
return Some(password);
}
println!("Authenticating to {url}");
prompt_secret(&format!("Password for {username}:")).ok()
}
fn prompt_ssh_key_passphrase(
&mut self,
private_key_path: &Path,
git_config: &git2::Config,
) -> Option<String> {
let password = self
.0
.passphrase_for_key(private_key_path)
.cloned()
.or_else(|| config_value(git_config, "autosave.password"));
if let Some(password) = password {
return Some(password);
}
prompt_secret(&format!(
"Passphrase for {}:",
private_key_path.to_string_lossy()
))
.ok()
}
}
|