Show more error context in the output of sq inspect.

- When showing why a key is not valid, or why a certification is not
    valid, `sq inspect` only showed the top-level error.

  - To make the issue clearer, show the whole error chain.

  - Fixes #237.
This commit is contained in:
Neal H. Walfield 2024-04-10 13:07:08 +02:00
parent d44ea64fa5
commit 3a0fc2fdb5
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3
2 changed files with 56 additions and 3 deletions

View File

@ -26,6 +26,7 @@ use cert_store::Store;
use crate::Convert;
use crate::Config;
use crate::one_line_error_chain;
use crate::SECONDS_IN_YEAR;
use crate::SECONDS_IN_DAY;
@ -379,12 +380,16 @@ fn inspect_key(
let vka = match ka.with_policy(policy, time) {
Ok(vka) => {
if let Err(e) = vka.alive() {
writeln!(output, "{} Invalid: {}", indent, e)?;
writeln!(output, "{} Invalid: {}",
indent,
one_line_error_chain(&e))?;
}
Some(vka)
},
Err(e) => {
writeln!(output, "{} Invalid: {}", indent, e)?;
writeln!(output, "{} Invalid: {}",
indent,
one_line_error_chain(&e))?;
None
},
};
@ -662,7 +667,8 @@ fn inspect_certifications<'a, A>(output: &mut dyn io::Write,
"{}Certification is not valid according to \
the current policy:\n\
{} {}",
indent, indent, err)?;
indent, indent,
one_line_error_chain(&err))?;
}
}
if emit_warning {

View File

@ -1384,3 +1384,50 @@ pub fn print_error_chain(err: &anyhow::Error) {
wprintln!(" {}", err);
err.chain().skip(1).for_each(|cause| wprintln!(" because: {}", cause));
}
/// Returns the error chain as a string.
///
/// The error and causes are separated by `error_separator`. The
/// causes are separated by `cause_separator`, or, if that is `None`,
/// `error_separator`.
pub fn display_error_chain<'a, E, C>(err: E,
error_separator: &str,
cause_separator: C)
-> String
where E: Borrow<anyhow::Error>,
C: Into<Option<&'a str>>
{
let err = err.borrow();
let cause_separator = cause_separator.into();
let error_chain = error_chain(err);
match error_chain.len() {
0 => unreachable!(),
1 => {
error_chain.into_iter().next().expect("have one")
}
2 => {
format!("{}{}{}",
error_chain[0],
error_separator,
error_chain[1])
}
_ => {
if let Some(cause_separator) = cause_separator {
format!("{}{}{}",
error_chain[0],
error_separator,
error_chain[1..].join(cause_separator))
} else {
error_chain.join(error_separator)
}
}
}
}
pub fn one_line_error_chain<E>(err: E) -> String
where E: Borrow<anyhow::Error>,
{
display_error_chain(err, ": ", ", because ")
}