use std::path::Path;
use std::process::Command;
use inquire::{Confirm, Text};
use super::config::{ConfigScope, ConfigValue, GitConfig};
#[allow(dead_code)] pub fn get_current_config(key: &str) -> Option<String> {
let output = Command::new("git")
.args(["config", "--global", "--get", key])
.output()
.ok()?;
if output.status.success() {
Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
} else {
None
}
}
#[allow(dead_code)] pub fn find_default_signing_key() -> String {
let home = dirs::home_dir().unwrap_or_default();
let keys = ["id_ed25519.pub", "id_ecdsa.pub", "id_rsa.pub"];
for key in keys {
let path = home.join(".ssh").join(key);
if path.exists() {
return path.to_string_lossy().to_string();
}
}
"~/.ssh/id_ed25519.pub".to_string()
}
#[allow(dead_code)] pub fn prompt_identity(existing: &GitConfig) -> Result<GitConfig, inquire::InquireError> {
let mut config = existing.clone();
let current_name = get_current_config("user.name");
let current_email = get_current_config("user.email");
if let (Some(name), Some(email)) = (¤t_name, ¤t_email) {
println!("\nGit identity already configured:");
println!(" Name: {name}");
println!(" Email: {email}");
let update = Confirm::new("Update Git identity?")
.with_default(false)
.prompt()?;
if !update {
return Ok(config);
}
}
println!("\nGit Configuration");
println!("=================\n");
let name = Text::new("Enter your name:")
.with_default(current_name.as_deref().unwrap_or(""))
.prompt()?;
if !name.is_empty() {
config.user_name = Some(ConfigValue::Plain(name));
}
let email = Text::new("Enter your email:")
.with_default(current_email.as_deref().unwrap_or(""))
.prompt()?;
if !email.is_empty() {
config.user_email = Some(ConfigValue::Plain(email));
}
let enable_signing = Confirm::new("Enable commit signing?")
.with_default(true)
.prompt()?;
if enable_signing {
config.signing = true;
let default_key = find_default_signing_key();
let key = Text::new("Path to signing key:")
.with_default(&default_key)
.with_help_message("SSH public key (.pub) or GPG key ID")
.prompt()?;
if !key.is_empty() {
let expanded = shellexpand::tilde(&key);
if Path::new(expanded.as_ref()).exists() {
config.signing_key = Some(key);
} else if !key.contains('/') && !key.contains('\\') {
config.signing_key = Some(key);
} else {
println!(" Warning: Signing key not found at {key}");
let proceed = Confirm::new("Continue anyway?")
.with_default(false)
.prompt()?;
if proceed {
config.signing_key = Some(key);
} else {
config.signing = false;
}
}
}
}
config.scope = ConfigScope::Global;
println!();
Ok(config)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_find_default_signing_key() {
let key = find_default_signing_key();
assert!(key.ends_with(".pub") || key.contains("id_"));
}
#[test]
fn test_get_current_config_invalid() {
let result = get_current_config("jarvy.nonexistent.key");
assert!(result.is_none());
}
}