substrate_manager/
lib.rs

1use anyhow::Error;
2use log::debug;
3use util::errors::AlreadyPrintedError;
4use util::indented_lines;
5
6use crate::core::shell::Verbosity::Verbose;
7use crate::{core::Shell, util::errors::InternalError};
8
9use util::{errors::VerboseError, CliError};
10
11pub mod core;
12pub mod ops;
13pub mod util;
14pub mod templates;
15
16pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
17    debug!("exit_with_error; err={:?}", err);
18
19    if let Some(ref err) = err.error {
20        if let Some(clap_err) = err.downcast_ref::<clap::Error>() {
21            let exit_code = if clap_err.use_stderr() { 1 } else { 0 };
22            let _ = clap_err.print();
23            std::process::exit(exit_code)
24        }
25    }
26
27    let CliError { error, exit_code } = err;
28    if let Some(error) = error {
29        display_error(&error, shell);
30    }
31
32    std::process::exit(exit_code)
33}
34
35/// Displays an error, and all its causes, to stderr.
36pub fn display_error(err: &Error, shell: &mut Shell) {
37    debug!("display_error; err={:?}", err);
38    _display_error(err, shell, true);
39    if err
40        .chain()
41        .any(|e| e.downcast_ref::<InternalError>().is_some())
42    {
43        drop(shell.note("this is an unexpected substrate-manager internal error"));
44        drop(
45            shell.note(
46                "we would appreciate a bug report: https://github.com/omerdn1/substrate-manager/issues/",
47            ),
48        );
49        // TODO: Show substrate-manager cli version
50        // drop(shell.note(format!("substrate {}", version())));
51    }
52}
53
54fn _display_error(err: &Error, shell: &mut Shell, as_err: bool) -> bool {
55    for (i, err) in err.chain().enumerate() {
56        // If we're not in verbose mode then only print cause chain until one
57        // marked as `VerboseError` appears.
58        //
59        // Generally the top error shouldn't be verbose, but check it anyways.
60        if shell.verbosity() != Verbose && err.is::<VerboseError>() {
61            return true;
62        }
63        if err.is::<AlreadyPrintedError>() {
64            break;
65        }
66        if i == 0 {
67            if as_err {
68                drop(shell.error(err));
69            } else {
70                drop(writeln!(shell.err(), "{}", err));
71            }
72        } else {
73            drop(writeln!(shell.err(), "\nCaused by:"));
74            drop(write!(shell.err(), "{}", indented_lines(&err.to_string())));
75        }
76    }
77    false
78}