use std::path::Path; use auth_git2::{GitAuthenticator, Prompter}; use git_autosave::{Config, commit_autosave, push_autosaves}; use git2::{RemoteCallbacks, Repository}; use inquire::{InquireError, PasswordDisplayMode}; #[derive(Default, Debug, Clone, PartialEq, Eq)] struct Inquirer(Config); fn config_value(git_config: &git2::Config, name: &str) -> Option { git_config .get_entry(name) .ok() .and_then(|entry| entry.value().map(|entry| entry.to_string())) } fn prompt_secret(message: &str) -> Result { 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 { 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 { 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() } } fn main() -> Result<(), anyhow::Error> { let repository = Repository::discover(".")?; let gitconfig = repository.config()?; let mut config = git_autosave::load_config()?; if std::env::args().any(|arg| arg == "--init") { git_autosave::init(&repository, Some(&mut config))?; git_autosave::save_config(&config)?; } let auth = GitAuthenticator::new().set_prompter(Inquirer(config)); let mut callbacks = RemoteCallbacks::new(); callbacks.credentials(auth.credentials(&gitconfig)); commit_autosave(&repository)?; push_autosaves(&repository, callbacks)?; Ok(()) }