fail fast on missing cli option values

This commit is contained in:
sabraman 2026-03-22 22:24:39 +03:00
parent e35d69c61f
commit 47a3cfc903
1 changed files with 13 additions and 1 deletions

View File

@ -12,6 +12,7 @@ use crate::transport::middle_proxy::{
ProxyConfigData, fetch_proxy_config_with_raw, load_proxy_config_cache, save_proxy_config_cache, ProxyConfigData, fetch_proxy_config_with_raw, load_proxy_config_cache, save_proxy_config_cache,
}; };
/// Resolves the runtime config path relative to the startup working directory.
pub(crate) fn resolve_runtime_config_path( pub(crate) fn resolve_runtime_config_path(
config_path_cli: &str, config_path_cli: &str,
startup_cwd: &std::path::Path, startup_cwd: &std::path::Path,
@ -25,6 +26,7 @@ pub(crate) fn resolve_runtime_config_path(
absolute.canonicalize().unwrap_or(absolute) absolute.canonicalize().unwrap_or(absolute)
} }
/// Parses CLI arguments and handles process-exiting utility commands.
pub(crate) fn parse_cli() -> (String, Option<PathBuf>, bool, Option<String>) { pub(crate) fn parse_cli() -> (String, Option<PathBuf>, bool, Option<String>) {
let mut config_path = "config.toml".to_string(); let mut config_path = "config.toml".to_string();
let mut data_path: Option<PathBuf> = None; let mut data_path: Option<PathBuf> = None;
@ -51,7 +53,7 @@ pub(crate) fn parse_cli() -> (String, Option<PathBuf>, bool, Option<String>) {
data_path = Some(PathBuf::from(args[i].clone())); data_path = Some(PathBuf::from(args[i].clone()));
} else { } else {
eprintln!("Missing value for --data-path"); eprintln!("Missing value for --data-path");
std::process::exit(0); std::process::exit(1);
} }
} }
s if s.starts_with("--data-path=") => { s if s.starts_with("--data-path=") => {
@ -66,6 +68,9 @@ pub(crate) fn parse_cli() -> (String, Option<PathBuf>, bool, Option<String>) {
i += 1; i += 1;
if i < args.len() { if i < args.len() {
log_level = Some(args[i].clone()); log_level = Some(args[i].clone());
} else {
eprintln!("Missing value for --log-level");
std::process::exit(1);
} }
} }
s if s.starts_with("--log-level=") => { s if s.starts_with("--log-level=") => {
@ -153,6 +158,7 @@ mod tests {
} }
} }
/// Logs Telegram proxy links derived from the active runtime configuration.
pub(crate) fn print_proxy_links(host: &str, port: u16, config: &ProxyConfig) { pub(crate) fn print_proxy_links(host: &str, port: u16, config: &ProxyConfig) {
info!(target: "telemt::links", "--- Proxy Links ({}) ---", host); info!(target: "telemt::links", "--- Proxy Links ({}) ---", host);
for user_name in config for user_name in config
@ -202,6 +208,7 @@ pub(crate) fn print_proxy_links(host: &str, port: u16, config: &ProxyConfig) {
info!(target: "telemt::links", "------------------------"); info!(target: "telemt::links", "------------------------");
} }
/// Persists the beobachten snapshot payload and creates parent directories when needed.
pub(crate) async fn write_beobachten_snapshot(path: &str, payload: &str) -> std::io::Result<()> { pub(crate) async fn write_beobachten_snapshot(path: &str, payload: &str) -> std::io::Result<()> {
if let Some(parent) = std::path::Path::new(path).parent() if let Some(parent) = std::path::Path::new(path).parent()
&& !parent.as_os_str().is_empty() && !parent.as_os_str().is_empty()
@ -211,10 +218,12 @@ pub(crate) async fn write_beobachten_snapshot(path: &str, payload: &str) -> std:
tokio::fs::write(path, payload).await tokio::fs::write(path, payload).await
} }
/// Returns the singular or plural unit label for a numeric value.
pub(crate) fn unit_label(value: u64, singular: &'static str, plural: &'static str) -> &'static str { pub(crate) fn unit_label(value: u64, singular: &'static str, plural: &'static str) -> &'static str {
if value == 1 { singular } else { plural } if value == 1 { singular } else { plural }
} }
/// Formats process uptime into a human-readable multi-unit string.
pub(crate) fn format_uptime(total_secs: u64) -> String { pub(crate) fn format_uptime(total_secs: u64) -> String {
const SECS_PER_MINUTE: u64 = 60; const SECS_PER_MINUTE: u64 = 60;
const SECS_PER_HOUR: u64 = 60 * SECS_PER_MINUTE; const SECS_PER_HOUR: u64 = 60 * SECS_PER_MINUTE;
@ -267,6 +276,7 @@ pub(crate) fn format_uptime(total_secs: u64) -> String {
format!("{} / {} seconds", parts.join(", "), total_secs) format!("{} / {} seconds", parts.join(", "), total_secs)
} }
/// Waits until admission opens or the watch channel closes.
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) async fn wait_until_admission_open(admission_rx: &mut watch::Receiver<bool>) -> bool { pub(crate) async fn wait_until_admission_open(admission_rx: &mut watch::Receiver<bool>) -> bool {
loop { loop {
@ -279,10 +289,12 @@ pub(crate) async fn wait_until_admission_open(admission_rx: &mut watch::Receiver
} }
} }
/// Identifies EOFs that match the expected empty-handshake shutdown path.
pub(crate) fn is_expected_handshake_eof(err: &crate::error::ProxyError) -> bool { pub(crate) fn is_expected_handshake_eof(err: &crate::error::ProxyError) -> bool {
err.to_string().contains("expected 64 bytes, got 0") err.to_string().contains("expected 64 bytes, got 0")
} }
/// Loads the startup proxy-config snapshot, falling back to the on-disk cache when needed.
pub(crate) async fn load_startup_proxy_config_snapshot( pub(crate) async fn load_startup_proxy_config_snapshot(
url: &str, url: &str,
cache_path: Option<&str>, cache_path: Option<&str>,