use auth_git2::GitAuthenticator;
use git2::{Config, ConfigLevel, RemoteCallbacks, Repository};
use crate::error::Result;
use crate::ssh_config::apply_identity_agent;
pub struct RemoteAuth {
authenticator: GitAuthenticator,
config: Config,
}
impl RemoteAuth {
pub fn callbacks(&self) -> RemoteCallbacks<'_> {
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(self.authenticator.credentials(&self.config));
callbacks
}
}
pub fn get_remote_callbacks(repo: &Repository, url: Option<&str>) -> Result<RemoteAuth> {
build_auth(repo.config()?, url)
}
pub fn get_remote_callbacks_default(url: Option<&str>) -> Result<RemoteAuth> {
build_auth(open_default_config_lenient()?, url)
}
fn build_auth(config: Config, url: Option<&str>) -> Result<RemoteAuth> {
if let Some(url) = url {
apply_identity_agent(url);
}
Ok(RemoteAuth {
authenticator: GitAuthenticator::default(),
config,
})
}
fn open_default_config_lenient() -> std::result::Result<Config, git2::Error> {
if let Ok(c) = Config::open_default() {
return Ok(c);
}
let mut config = Config::new()?;
if let Ok(path) = Config::find_global() {
let _ = config.add_file(&path, ConfigLevel::Global, false);
}
if let Ok(path) = Config::find_xdg() {
let _ = config.add_file(&path, ConfigLevel::XDG, false);
}
if let Ok(path) = Config::find_system() {
let _ = config.add_file(&path, ConfigLevel::System, false);
}
Ok(config)
}