use std::{error::Error, path::PathBuf};
use clap::Args;
use tari_common::configuration::{ConfigOverrideProvider, Network};
#[derive(Args, Debug)]
pub struct CommonCliArgs {
#[clap(
short,
long,
aliases = &["base_path", "base_dir", "base-dir"],
default_value_t= defaults::base_path(),
env = "TARI_BASE_DIR"
)]
pub base_path: String,
#[clap(short, long, default_value_t= defaults::config())]
pub config: String,
#[clap(short, long, alias = "log_config")]
pub log_config: Option<PathBuf>,
#[clap(long, alias = "log_path")]
pub log_path: Option<PathBuf>,
#[clap(long, env = "TARI_NETWORK")]
pub network: Option<Network>,
#[clap(short = 'p', value_parser = parse_key_val::<String, String>, action = clap::ArgAction::Append)]
pub config_property_overrides: Vec<(String, String)>,
}
fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
where
T: std::str::FromStr,
T::Err: Error + Send + Sync + 'static,
U: std::str::FromStr,
U::Err: Error + Send + Sync + 'static,
{
let mut parts = s.split('=').map(|s| s.trim());
let k = parts.next().ok_or("invalid override: string empty`")?;
let v = parts
.next()
.ok_or_else(|| format!("invalid override: expected key=value: no `=` found in `{s}`"))?;
Ok((k.parse()?, v.parse()?))
}
impl CommonCliArgs {
pub fn config_path(&self) -> PathBuf {
let config_path = PathBuf::from(&self.config);
if config_path.is_absolute() {
config_path
} else {
self.get_base_path().join(config_path)
}
}
pub fn get_base_path(&self) -> PathBuf {
let network = self.network.unwrap_or_default();
PathBuf::from(&self.base_path).join(network.to_string())
}
pub fn log_config_path(&self, application_name: &str) -> PathBuf {
if let Some(ref log_config) = self.log_config {
let path = PathBuf::from(log_config);
if path.is_absolute() {
log_config.clone()
} else {
self.get_base_path().join(log_config)
}
} else {
self.get_base_path()
.join("config")
.join(application_name)
.join("log4rs.yml")
}
}
}
impl ConfigOverrideProvider for CommonCliArgs {
fn get_config_property_overrides(&self, _network: &Network) -> Vec<(String, String)> {
let mut overrides = self.config_property_overrides.clone();
overrides.push((
"common.base_path".to_string(),
self.get_base_path()
.as_os_str()
.to_str()
.expect("An os string from a path")
.into(),
));
overrides
}
}
mod defaults {
use tari_common::dir_utils;
const DEFAULT_CONFIG: &str = "config/config.toml";
pub(super) fn base_path() -> String {
dir_utils::default_path("", None).to_string_lossy().to_string()
}
pub(super) fn config() -> String {
DEFAULT_CONFIG.to_string()
}
}