diff options
| author | Mica White <botahamec@outlook.com> | 2026-03-29 10:54:31 -0400 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2026-03-29 10:54:31 -0400 |
| commit | 604d3be6dc04892cdef71935d1117855c1cc7bb4 (patch) | |
| tree | 7f3aef3e2ae263355c94faa4da445898434ffb7c /src | |
| parent | 766ef91c4b4226a645583eff311d2868cab28bc0 (diff) | |
Get password from root config
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/git-autosave.rs | 113 | ||||
| -rw-r--r-- | src/bin/git-init-autosave.rs | 10 | ||||
| -rw-r--r-- | src/lib.rs | 20 |
3 files changed, 141 insertions, 2 deletions
diff --git a/src/bin/git-autosave.rs b/src/bin/git-autosave.rs new file mode 100644 index 0000000..3df94b6 --- /dev/null +++ b/src/bin/git-autosave.rs @@ -0,0 +1,113 @@ +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<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() + } +} + +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(()) +} diff --git a/src/bin/git-init-autosave.rs b/src/bin/git-init-autosave.rs new file mode 100644 index 0000000..df3b66d --- /dev/null +++ b/src/bin/git-init-autosave.rs @@ -0,0 +1,10 @@ +use git2::Repository; +use git_autosave::{init, load_config, save_config}; + +fn main() -> Result<(), anyhow::Error> { + let repository = Repository::discover(".")?; + let mut config = load_config()?; + init(&repository, Some(&mut config))?; + save_config(&config)?; + Ok(()) +} @@ -39,7 +39,7 @@ * - allow force */ -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::fs::Metadata; use std::path::{Path, PathBuf}; @@ -49,9 +49,25 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use uuid::Uuid; -#[derive(Default, Serialize, Deserialize)] +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Config { repositories: HashSet<PathBuf>, + passwords: HashMap<String, (Option<String>, String)>, + passphrases: HashMap<PathBuf, String>, +} + +impl Config { + pub fn username_for_url(&self, url: &str) -> Option<&String> { + self.passwords.get(url)?.0.as_ref() + } + + pub fn password_for_url(&self, url: &str) -> Option<&String> { + Some(&self.passwords.get(url)?.1) + } + + pub fn passphrase_for_key(&self, key: &Path) -> Option<&String> { + self.passphrases.get(key) + } } #[derive(Debug, Error)] |
