use crev_lib::VerificationStatus;
use std::{
env,
fmt::Arguments,
io::{self, Write},
};
use term::{
self,
color::{self, Color},
StderrTerminal, StdoutTerminal,
};
pub fn verification_status_color(s: VerificationStatus) -> Option<color::Color> {
use VerificationStatus::*;
match s {
Verified | Local => Some(term::color::GREEN),
Insufficient => None,
Negative => Some(term::color::YELLOW),
}
}
pub fn known_owners_count_color(count: u64) -> Option<color::Color> {
if count > 0 {
Some(color::GREEN)
} else {
None
}
}
pub struct Term {
pub stdout_is_tty: bool,
stderr_is_tty: bool,
stdin_is_tty: bool,
stdout: Option<Box<StdoutTerminal>>,
#[allow(unused)]
stderr: Option<Box<StderrTerminal>>,
}
fn output_to<O>(
args: std::fmt::Arguments<'_>,
color: Option<Color>,
term: &mut dyn term::Terminal<Output = O>,
is_tty: bool,
) -> io::Result<()>
where
O: Write,
{
let use_color = is_tty && term.supports_color();
if use_color {
if let Some(color) = color {
term.fg(color)?
}
}
term.get_mut().write_fmt(args)?;
if use_color && color.is_some() {
term.reset()?;
}
Ok(())
}
impl Term {
pub fn new() -> Term {
Term {
stdout: term::stdout(),
stderr: term::stderr(),
stdin_is_tty: atty::is(atty::Stream::Stdin),
stdout_is_tty: atty::is(atty::Stream::Stdout),
stderr_is_tty: atty::is(atty::Stream::Stderr),
}
}
pub fn print<C>(&mut self, fmt: Arguments<'_>, color: C) -> io::Result<()>
where
C: Into<Option<Color>>,
{
let color = color.into();
if let Some(ref mut term) = self.stdout {
output_to(
fmt,
color,
(&mut **term) as &mut dyn term::Terminal<Output = _>,
self.stdout_is_tty,
)?;
}
Ok(())
}
pub fn eprint<C>(&mut self, fmt: Arguments<'_>, color: C) -> io::Result<()>
where
C: Into<Option<Color>>,
{
let color = color.into();
if let Some(ref mut term) = self.stderr {
output_to(
fmt,
color,
(&mut **term) as &mut dyn term::Terminal<Output = _>,
self.stdout_is_tty,
)?;
}
Ok(())
}
pub fn eprintln<C>(&mut self, fmt: Arguments<'_>, color: C) -> io::Result<()>
where
C: Into<Option<Color>>,
{
let color = color.into();
self.print(fmt, color)?;
self.print(format_args!("\n"), color)?;
Ok(())
}
pub(crate) fn is_interactive(&self) -> bool {
self.stderr_is_tty && self.stdout_is_tty
}
pub(crate) fn is_input_interactive(&self) -> bool {
self.stdin_is_tty
}
}
pub fn read_passphrase() -> io::Result<String> {
if let Ok(pass) = env::var("CREV_PASSPHRASE") {
eprintln!("Using passphrase set in CREV_PASSPHRASE");
return Ok(pass);
} else if let Some(cmd) = env::var_os("CREV_PASSPHRASE_CMD") {
return Ok(
String::from_utf8_lossy(&crev_common::run_with_shell_cmd_capture_stdout(&cmd, None)?)
.trim()
.to_owned(),
);
}
eprint!("Enter passphrase to unlock: ");
rpassword::read_password()
}
pub fn read_new_passphrase() -> io::Result<String> {
if let Ok(pass) = env::var("CREV_PASSPHRASE") {
eprintln!("Using passphrase set in CREV_PASSPHRASE");
return Ok(pass);
}
loop {
eprint!("Enter new passphrase: ");
let p1 = rpassword::read_password()?;
eprint!("Enter new passphrase again: ");
let p2 = rpassword::read_password()?;
if p1 == p2 {
return Ok(p1);
}
eprintln!("\nPassphrases don't match, try again.");
}
}