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