100 lines
3.3 KiB
Rust
100 lines
3.3 KiB
Rust
//! Integration with `clap`
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use clap::Parser;
|
|
use conduwuit::{
|
|
config::{Figment, FigmentValue},
|
|
err, toml,
|
|
utils::available_parallelism,
|
|
Err, Result,
|
|
};
|
|
|
|
/// Commandline arguments
|
|
#[derive(Parser, Debug)]
|
|
#[clap(version = conduwuit::version(), about, long_about = None, name = "conduwuit")]
|
|
pub(crate) struct Args {
|
|
#[arg(short, long)]
|
|
/// Path to the config TOML file (optional)
|
|
pub(crate) config: Option<Vec<PathBuf>>,
|
|
|
|
/// Override a configuration variable using TOML 'key=value' syntax
|
|
#[arg(long, short('O'))]
|
|
pub(crate) option: Vec<String>,
|
|
|
|
#[cfg(feature = "console")]
|
|
/// Activate admin command console automatically after startup.
|
|
#[arg(long, num_args(0))]
|
|
pub(crate) console: bool,
|
|
|
|
/// Execute console command automatically after startup.
|
|
#[arg(long)]
|
|
pub(crate) execute: Vec<String>,
|
|
|
|
/// Set functional testing modes if available. Ex '--test=smoke'
|
|
#[arg(long, hide(true))]
|
|
pub(crate) test: Vec<String>,
|
|
|
|
/// Override the tokio worker_thread count.
|
|
#[arg(long, hide(true), env = "TOKIO_WORKER_THREADS", default_value = available_parallelism().to_string())]
|
|
pub(crate) worker_threads: usize,
|
|
|
|
/// Set the histogram bucket size, in microseconds (tokio_unstable). Default
|
|
/// is 25 microseconds. If the values of the histogram don't approach zero
|
|
/// with the exception of the last bucket, try increasing this value to e.g.
|
|
/// 50 or 100. Inversely, decrease to 10 etc if the histogram lacks
|
|
/// resolution.
|
|
#[arg(long, hide(true), env = "CONDUWUIT_RUNTIME_HISTOGRAM_INTERVAL", default_value = "25")]
|
|
pub(crate) worker_histogram_interval: u64,
|
|
|
|
/// Set the histogram bucket count (tokio_unstable). Default is 20.
|
|
#[arg(long, hide(true), env = "CONDUWUIT_RUNTIME_HISTOGRAM_BUCKETS", default_value = "20")]
|
|
pub(crate) worker_histogram_buckets: usize,
|
|
}
|
|
|
|
/// Parse commandline arguments into structured data
|
|
#[must_use]
|
|
pub(super) fn parse() -> Args { Args::parse() }
|
|
|
|
/// Synthesize any command line options with configuration file options.
|
|
pub(crate) fn update(mut config: Figment, args: &Args) -> Result<Figment> {
|
|
#[cfg(feature = "console")]
|
|
// Indicate the admin console should be spawned automatically if the
|
|
// configuration file hasn't already.
|
|
if args.console {
|
|
config = config.join(("admin_console_automatic", true));
|
|
}
|
|
|
|
// Execute commands after any commands listed in configuration file
|
|
config = config.adjoin(("admin_execute", &args.execute));
|
|
|
|
// Update config with names of any functional-tests
|
|
config = config.adjoin(("test", &args.test));
|
|
|
|
// All other individual overrides can go last in case we have options which
|
|
// set multiple conf items at once and the user still needs granular overrides.
|
|
for option in &args.option {
|
|
let (key, val) = option
|
|
.split_once('=')
|
|
.ok_or_else(|| err!("Missing '=' in -O/--option: {option:?}"))?;
|
|
|
|
if key.is_empty() {
|
|
return Err!("Missing key= in -O/--option: {option:?}");
|
|
}
|
|
|
|
if val.is_empty() {
|
|
return Err!("Missing =val in -O/--option: {option:?}");
|
|
}
|
|
|
|
// The value has to pass for what would appear as a line in the TOML file.
|
|
let val = toml::from_str::<FigmentValue>(option)?;
|
|
let FigmentValue::Dict(_, val) = val else {
|
|
panic!("Unexpected Figment Value: {val:#?}");
|
|
};
|
|
|
|
// Figment::merge() overrides existing
|
|
config = config.merge((key, val[key].clone()));
|
|
}
|
|
|
|
Ok(config)
|
|
}
|