summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2026-03-29 10:54:31 -0400
committerMica White <botahamec@outlook.com>2026-03-29 10:54:31 -0400
commit604d3be6dc04892cdef71935d1117855c1cc7bb4 (patch)
tree7f3aef3e2ae263355c94faa4da445898434ffb7c /src
parent766ef91c4b4226a645583eff311d2868cab28bc0 (diff)
Get password from root config
Diffstat (limited to 'src')
-rw-r--r--src/bin/git-autosave.rs113
-rw-r--r--src/bin/git-init-autosave.rs10
-rw-r--r--src/lib.rs20
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(())
+}
diff --git a/src/lib.rs b/src/lib.rs
index d592003..2882039 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)]