From d2f423521ec76406944ad83098ec33afe20c692b Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Mon, 9 Jan 2023 13:18:33 +0100 Subject: This is it Squashed commit of all the exploration history. Development starts here. Signed-off-by: Kim Altintop --- src/cmd/ui.rs | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/cmd/ui.rs (limited to 'src/cmd/ui.rs') diff --git a/src/cmd/ui.rs b/src/cmd/ui.rs new file mode 100644 index 0000000..c1ad214 --- /dev/null +++ b/src/cmd/ui.rs @@ -0,0 +1,131 @@ +// Copyright © 2022 Kim Altintop +// SPDX-License-Identifier: GPL-2.0-only WITH openvpn-openssl-exception + +use std::{ + borrow::Cow, + env, + ffi::OsStr, + io, + process::{ + self, + Command, + Stdio, + }, +}; + +use anyhow::ensure; +use console::Term; +use zeroize::Zeroizing; + +use crate::{ + cmd::{ + self, + Aborted, + }, + patches::notes, +}; + +mod editor; +mod output; +pub use output::{ + debug, + error, + info, + warn, + Output, +}; + +pub fn edit_commit_message( + repo: &git2::Repository, + branch: &str, + old: &git2::Tree, + new: &git2::Tree, +) -> cmd::Result { + let diff = repo.diff_tree_to_tree( + Some(old), + Some(new), + Some( + git2::DiffOptions::new() + .patience(true) + .minimal(true) + .context_lines(5), + ), + )?; + abort_if_empty( + "commit message", + editor::Commit::new(repo.path())?.edit(branch, diff), + ) +} + +pub fn edit_cover_letter(repo: &git2::Repository) -> cmd::Result { + abort_if_empty( + "cover letter", + editor::CoverLetter::new(repo.path())?.edit(), + ) +} + +pub fn edit_comment( + repo: &git2::Repository, + re: Option<¬es::Simple>, +) -> cmd::Result { + abort_if_empty("comment", editor::Comment::new(repo.path())?.edit(re)) +} + +pub fn edit_metadata(template: T) -> cmd::Result +where + T: serde::Serialize + serde::de::DeserializeOwned, +{ + abort_if_empty("metadata", editor::Metadata::new()?.edit(template)) +} + +fn abort_if_empty(ctx: &str, edit: io::Result>) -> cmd::Result { + edit?.map(Ok).unwrap_or_else(|| { + info!("Aborting due to empty {ctx}"); + cmd::abort!() + }) +} + +pub fn askpass(prompt: &str) -> cmd::Result>> { + const DEFAULT_ASKPASS: &str = "ssh-askpass"; + + fn ssh_askpass() -> Cow<'static, OsStr> { + env::var_os("SSH_ASKPASS") + .map(Into::into) + .unwrap_or_else(|| OsStr::new(DEFAULT_ASKPASS).into()) + } + + let ssh = env::var_os("SSH_ASKPASS_REQUIRE").and_then(|require| { + if require == "force" { + Some(ssh_askpass()) + } else if require == "prefer" { + env::var_os("DISPLAY").map(|_| ssh_askpass()) + } else { + None + } + }); + + match ssh { + Some(cmd) => { + let process::Output { status, stdout, .. } = Command::new(&cmd) + .arg(prompt) + .stderr(Stdio::inherit()) + .output()?; + ensure!( + status.success(), + "{} failed with {:?}", + cmd.to_string_lossy(), + status.code() + ); + Ok(Zeroizing::new(stdout)) + }, + None => { + let tty = Term::stderr(); + if tty.is_term() { + tty.write_line(prompt)?; + } + tty.read_secure_line() + .map(|s| Zeroizing::new(s.into_bytes())) + .map_err(Into::into) + }, + } +} -- cgit v1.2.3