Adding upstream version 0.5.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
dde4be91ba
commit
d2d6608958
17 changed files with 2615 additions and 0 deletions
139
examples/custom-prompt-clone.rs
Normal file
139
examples/custom-prompt-clone.rs
Normal file
|
@ -0,0 +1,139 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct YadPrompter;
|
||||
|
||||
impl auth_git2::Prompter for YadPrompter {
|
||||
fn prompt_username_password(&mut self, url: &str, _git_config: &git2::Config) -> Option<(String, String)> {
|
||||
let mut items = yad_prompt(
|
||||
"Git authentication",
|
||||
&format!("Authentication required for {url}"),
|
||||
&["Username", "Password:H"],
|
||||
).ok()?.into_iter();
|
||||
let username = items.next()?;
|
||||
let password = items.next()?;
|
||||
Some((username, password))
|
||||
}
|
||||
|
||||
fn prompt_password(&mut self, username: &str, url: &str, _git_config: &git2::Config) -> Option<String> {
|
||||
let mut items = yad_prompt(
|
||||
"Git authentication",
|
||||
&format!("Authentication required for {url}"),
|
||||
&[&format!("Username: {username}:LBL"), "Password:H"],
|
||||
).ok()?.into_iter();
|
||||
let password = items.next()?;
|
||||
Some(password)
|
||||
}
|
||||
|
||||
fn prompt_ssh_key_passphrase(&mut self, private_key_path: &std::path::Path, _git_config: &git2::Config) -> Option<String> {
|
||||
let mut items = yad_prompt(
|
||||
"Git authentication",
|
||||
&format!("Passphrase required for {}", private_key_path.display()),
|
||||
&["Passphrase:H"],
|
||||
).ok()?.into_iter();
|
||||
let passphrase = items.next()?;
|
||||
Some(passphrase)
|
||||
}
|
||||
}
|
||||
|
||||
fn yad_prompt(title: &str, text: &str, fields: &[&str]) -> Result<Vec<String>, ()> {
|
||||
let mut command = std::process::Command::new("yad");
|
||||
command
|
||||
.arg("--title")
|
||||
.arg(title)
|
||||
.arg("--text")
|
||||
.arg(text)
|
||||
.arg("--form")
|
||||
.arg("--separator=\n");
|
||||
for field in fields {
|
||||
command.arg("--field");
|
||||
command.arg(field);
|
||||
}
|
||||
|
||||
let output = command
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.output()
|
||||
.map_err(|e| log::error!("Failed to run `yad`: {e}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
log::debug!("yad exited with {}", output.status);
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let output = String::from_utf8(output.stdout)
|
||||
.map_err(|_| log::warn!("Invalid UTF-8 in response from yad"))?;
|
||||
|
||||
let mut items: Vec<_> = output.splitn(fields.len() + 1, '\n')
|
||||
.take(fields.len())
|
||||
.map(|x| x.to_owned())
|
||||
.collect();
|
||||
if let Some(last) = items.pop() {
|
||||
if !last.is_empty() {
|
||||
items.push(last)
|
||||
}
|
||||
}
|
||||
|
||||
if items.len() != fields.len() {
|
||||
log::error!("asked yad for {} values but got only {}", fields.len(), items.len());
|
||||
Err(())
|
||||
} else {
|
||||
Ok(items)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
struct Options {
|
||||
/// Show more verbose statement.
|
||||
#[clap(long, short)]
|
||||
#[clap(global = true)]
|
||||
#[clap(action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
|
||||
/// The URL of the repository to clone.
|
||||
#[clap(value_name = "URL")]
|
||||
repo: String,
|
||||
|
||||
/// The path where to clone the repository.
|
||||
#[clap(value_name = "PATH")]
|
||||
local_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(()) = do_main(clap::Parser::parse()) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn log_level(verbose: u8) -> log::LevelFilter {
|
||||
match verbose {
|
||||
0 => log::LevelFilter::Info,
|
||||
1 => log::LevelFilter::Debug,
|
||||
2.. => log::LevelFilter::Trace,
|
||||
}
|
||||
}
|
||||
|
||||
fn do_main(options: Options) -> Result<(), ()> {
|
||||
let log_level = log_level(options.verbose);
|
||||
env_logger::builder()
|
||||
.parse_default_env()
|
||||
.filter_module(module_path!(), log_level)
|
||||
.filter_module("auth_git2", log_level)
|
||||
.init();
|
||||
|
||||
let local_path = options.local_path.as_deref()
|
||||
.unwrap_or_else(|| Path::new(repo_name_from_url(&options.repo)));
|
||||
|
||||
log::info!("Cloning {} into {}", options.repo, local_path.display());
|
||||
|
||||
let auth = auth_git2::GitAuthenticator::default()
|
||||
.set_prompter(YadPrompter);
|
||||
auth.clone_repo(&options.repo, local_path)
|
||||
.map_err(|e| log::error!("Failed to clone {}: {}", options.repo, e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn repo_name_from_url(url: &str) -> &str {
|
||||
url.rsplit_once('/')
|
||||
.map(|(_head, tail)| tail)
|
||||
.unwrap_or(url)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue