1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
//! Zebrad Subcommands
use std::path::PathBuf;
use abscissa_core::{config::Override, Command, Configurable, FrameworkError, Runnable};
use crate::config::ZebradConfig;
pub use self::{entry_point::EntryPoint, start::StartCmd};
use self::{copy_state::CopyStateCmd, generate::GenerateCmd, tip_height::TipHeightCmd};
pub mod start;
mod copy_state;
mod entry_point;
mod generate;
mod tip_height;
#[cfg(test)]
mod tests;
use ZebradCmd::*;
/// Zebrad Configuration Filename
pub const CONFIG_FILE: &str = "zebrad.toml";
/// Zebrad Subcommands
#[derive(Command, Debug, clap::Subcommand)]
pub enum ZebradCmd {
/// The `copy-state` subcommand, used to debug cached chain state (expert users only)
// TODO: hide this command from users in release builds (#3279)
CopyState(CopyStateCmd),
/// Generate a default `zebrad.toml` configuration
Generate(GenerateCmd),
/// Start the application (default command)
Start(StartCmd),
/// Print the tip block height of Zebra's chain state on disk
TipHeight(TipHeightCmd),
}
impl ZebradCmd {
/// Returns true if this command is a server command.
///
/// Servers load extra components, and use the configured tracing filter.
///
/// For example, `Start` acts as a Zcash node.
pub(crate) fn is_server(&self) -> bool {
// List all the commands, so new commands have to make a choice here
match self {
// Commands that run as a configured server
CopyState(_) | Start(_) => true,
// Utility commands that don't use server components
Generate(_) | TipHeight(_) => false,
}
}
/// Returns true if this command shows the Zebra intro logo and text.
///
/// For example, `Start` acts as a Zcash node.
pub(crate) fn uses_intro(&self) -> bool {
// List all the commands, so new commands have to make a choice here
match self {
// Commands that need an intro
Start(_) => true,
// Utility commands
CopyState(_) | Generate(_) | TipHeight(_) => false,
}
}
/// Returns true if this command should ignore errors when
/// attempting to load a config file.
pub(crate) fn should_ignore_load_config_error(&self) -> bool {
matches!(self, ZebradCmd::Generate(_))
}
/// Returns the default log level for this command, based on the `verbose` command line flag.
///
/// Some commands need to be quiet by default.
pub(crate) fn default_tracing_filter(&self, verbose: bool) -> &'static str {
let only_show_warnings = match self {
// Commands that generate quiet output by default.
// This output:
// - is used by automated tools, or
// - needs to be read easily.
Generate(_) | TipHeight(_) => true,
// Commands that generate informative logging output by default.
CopyState(_) | Start(_) => false,
};
if only_show_warnings && !verbose {
"warn"
} else if only_show_warnings || !verbose {
"info"
} else {
"debug"
}
}
}
impl Runnable for ZebradCmd {
fn run(&self) {
match self {
CopyState(cmd) => cmd.run(),
Generate(cmd) => cmd.run(),
Start(cmd) => cmd.run(),
TipHeight(cmd) => cmd.run(),
}
}
}
/// This trait allows you to define how application configuration is loaded.
impl Configurable<ZebradConfig> for ZebradCmd {
/// Location of the configuration file
fn config_path(&self) -> Option<PathBuf> {
let if_exists = |f: PathBuf| if f.exists() { Some(f) } else { None };
dirs::preference_dir()
.map(|path| path.join(CONFIG_FILE))
.and_then(if_exists)
// Note: Changes in how configuration is loaded may need usage
// edits in generate.rs
}
/// Apply changes to the config after it's been loaded, e.g. overriding
/// values in a config file using command-line options.
///
/// This can be safely deleted if you don't want to override config
/// settings from command-line options.
fn process_config(&self, config: ZebradConfig) -> Result<ZebradConfig, FrameworkError> {
match self {
ZebradCmd::Start(cmd) => cmd.override_config(config),
_ => Ok(config),
}
}
}