|
| 1 | +#[cfg(any(unix, feature = "json"))] |
| 2 | +use std::path::PathBuf; |
| 3 | + |
| 4 | +use clap::{CommandFactory, FromArgMatches, Parser}; |
| 5 | +use concat_with::concat_line; |
| 6 | +use terminal_size::terminal_size; |
| 7 | + |
| 8 | +const APP_NAME: &str = "wait-service"; |
| 9 | +const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); |
| 10 | +const CARGO_PKG_AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); |
| 11 | + |
| 12 | +const AFTER_HELP: &str = "Enjoy it! https://magiclen.org"; |
| 13 | + |
| 14 | +const APP_ABOUT: &str = concat!( |
| 15 | + "Wait Service is a pure rust program to test and wait on the availability of multiple \ |
| 16 | + services\n\nEXAMPLES:\n", |
| 17 | + concat_line!(prefix "wait-service ", |
| 18 | + "--tcp localhost:27017 --tcp localhost:27018 -t 5 -- npm start # Wait for localhost:27017 and localhost:27018 (max 5 seconds) and then run `npm start`", |
| 19 | + "--tcp localhost:27017 --uds /var/run/app.sock -t 0 -- npm start # Wait for localhost:27017 and /var/run/app.sock (forever) and then run `npm start`", |
| 20 | + "--uds /var/run/app.sock --json /path/to/json -- npm start # Wait for /var/run/app.sock and other services defined in the json file (max 60 seconds) and then run `npm start`", |
| 21 | + ) |
| 22 | +); |
| 23 | + |
| 24 | +#[derive(Debug, Parser)] |
| 25 | +#[command(name = APP_NAME)] |
| 26 | +#[command(term_width = terminal_size().map(|(width, _)| width.0 as usize).unwrap_or(0))] |
| 27 | +#[command(version = CARGO_PKG_VERSION)] |
| 28 | +#[command(author = CARGO_PKG_AUTHORS)] |
| 29 | +#[command(after_help = AFTER_HELP)] |
| 30 | +pub struct CLIArgs { |
| 31 | + #[arg(short, long)] |
| 32 | + #[arg(default_value = "60")] |
| 33 | + #[arg(help = "Set the timeout in seconds, zero for no timeout")] |
| 34 | + pub timeout: u64, |
| 35 | + |
| 36 | + #[arg(required = true)] |
| 37 | + #[arg(last = true)] |
| 38 | + #[arg(value_hint = clap::ValueHint::CommandWithArguments)] |
| 39 | + #[arg(help = "Command to execute after service is available")] |
| 40 | + pub command: Vec<String>, |
| 41 | + |
| 42 | + #[arg(long)] |
| 43 | + #[arg(num_args = 1..)] |
| 44 | + #[cfg_attr(unix, cfg_attr(feature = "json", arg(required_unless_present_any = ["uds", "json"], required_unless_present = "uds")), cfg_attr(feature = "json", arg(required_unless_present = "json")))] |
| 45 | + #[arg(help = "Test and wait on the availability of TCP services")] |
| 46 | + pub tcp: Vec<String>, |
| 47 | + |
| 48 | + #[cfg(unix)] |
| 49 | + #[arg(long, visible_alias = "unix")] |
| 50 | + #[arg(num_args = 1..)] |
| 51 | + #[cfg_attr(feature = "json", arg(required_unless_present_any = ["tcp", "json"]), arg(required_unless_present = "tcp"))] |
| 52 | + #[arg(value_hint = clap::ValueHint::FilePath)] |
| 53 | + #[arg(help = "Test and wait on the availability of UDS services")] |
| 54 | + pub uds: Vec<PathBuf>, |
| 55 | + |
| 56 | + #[cfg(feature = "json")] |
| 57 | + #[arg(long)] |
| 58 | + #[arg(num_args = 1..)] |
| 59 | + #[cfg_attr(unix, arg(required_unless_present_any = ["tcp", "uds"]), arg(required_unless_present = "tcp"))] |
| 60 | + #[arg(value_hint = clap::ValueHint::FilePath)] |
| 61 | + #[arg(help = "Test and wait on the availability of TCP or UDS services")] |
| 62 | + pub json: Vec<PathBuf>, |
| 63 | +} |
| 64 | + |
| 65 | +pub fn get_args() -> CLIArgs { |
| 66 | + let args = CLIArgs::command(); |
| 67 | + |
| 68 | + let about = format!("{APP_NAME} {CARGO_PKG_VERSION}\n{CARGO_PKG_AUTHORS}\n{APP_ABOUT}"); |
| 69 | + |
| 70 | + let args = args.about(about); |
| 71 | + |
| 72 | + let matches = args.get_matches(); |
| 73 | + |
| 74 | + match CLIArgs::from_arg_matches(&matches) { |
| 75 | + Ok(args) => args, |
| 76 | + Err(err) => { |
| 77 | + err.exit(); |
| 78 | + }, |
| 79 | + } |
| 80 | +} |
0 commit comments