1pub mod cli;
2pub use cli::build_cli;
3
4use clap::ArgMatches;
5use clap::error::ErrorKind;
6use clap_complete::{Shell, generate_to};
7use tracing::span;
8
9use std::process::ExitCode;
10use std::str::FromStr;
11
12use crate::cli::otel::OtelConfig;
13use crate::cli::otel::init_logging;
14pub fn handle_matches(
15 matches: &Result<ArgMatches, clap::Error>,
16 raw_args: Option<Vec<String>>,
17) -> Result<(), ExitCode> {
18 let raw_args = if let Some(args) = raw_args {
19 args
20 } else {
21 std::env::args_os()
23 .skip(1)
24 .map(|arg| arg.to_string_lossy().into_owned())
25 .collect()
26 };
27 match matches {
28 Ok(results) => {
29 let (
30 enable_otel,
31 enable_otel_logs,
32 enable_otel_traces,
33 otel_exporter,
34 otel_exporter_endpoint,
35 otel_exporter_protocol,
36 log_level,
37 ) = match &matches {
38 Ok(m) => (
39 m.get_flag("enable-otel"),
40 m.get_flag("enable-otel-logs"),
41 m.get_flag("enable-otel-traces"),
42 m.get_one::<String>("otel-exporter").map(|s| {
43 s.split(',')
44 .map(|v| v.trim().to_string())
45 .collect::<Vec<String>>()
46 }),
47 m.get_one::<String>("otel-exporter-endpoint"),
48 m.get_one::<String>("otel-exporter-protocol"),
49 m.get_one::<String>("log-level")
50 .and_then(|lvl| lvl.parse::<tracing::Level>().ok()),
51 ),
52 Err(_) => (false, false, false, None, None, None, None),
53 };
54 let otel_config = OtelConfig {
55 enable_otel: Some(enable_otel),
56 enable_logs: Some(enable_otel_logs),
57 enable_traces: Some(enable_otel_traces),
58 exporter: otel_exporter,
59 endpoint: otel_exporter_endpoint.cloned(),
60 protocol: otel_exporter_protocol.cloned(),
61 log_level,
62 };
63 let tracer_provider = init_logging(otel_config);
64 let _tracer_provider_dropper;
65 if let Some(tp) = tracer_provider {
66 _tracer_provider_dropper = crate::cli::otel::TracerProviderDropper(tp);
67 }
68
69 let span = if tracing::Span::current().is_none() {
70 span!(tracing::Level::INFO, "pact-broker-cli")
71 } else {
72 tracing::Span::current()
73 };
74 let _enter = span.enter();
75
76 match results.subcommand() {
77 Some(("pactflow", args)) => match cli::pactflow_client::run(args) {
78 Ok(_) => Ok(()),
79 Err(error) => Err(ExitCode::from(error as u8)),
80 },
81 Some(("completions", args)) => {
82 generate_completions(args);
83 Ok(())
84 }
85 _ => match cli::pact_broker_client::run(results, raw_args) {
86 Ok(_) => Ok(()),
87 Err(error) => Err(ExitCode::from(error as u8)),
88 },
89 }
90 }
91 Err(err) => match err.kind() {
92 ErrorKind::DisplayHelp => {
93 let _ = err.print();
94 Ok(())
95 }
96 ErrorKind::DisplayVersion => {
97 let _ = err.print();
98 Ok(())
99 }
100 ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand => {
101 let _ = err.print();
102 Ok(())
103 }
104 _ => err.exit(),
105 },
106 }
107}
108
109fn generate_completions(args: &ArgMatches) {
110 let shell = args
111 .get_one::<String>("shell")
112 .expect("a shell is required");
113 let out_dir = args
114 .get_one::<String>("dir")
115 .expect("a directory is expected")
116 .to_string();
117 let mut cmd = cli::build_cli();
118 let shell_enum = Shell::from_str(shell).unwrap();
119 let _ = generate_to(
120 shell_enum,
121 &mut cmd,
122 "pact-broker-cli".to_string(),
123 &out_dir,
124 );
125 println!(
126 "ℹ️ {} shell completions for pact-broker-cli written to {}",
127 shell_enum, out_dir
128 );
129}