1pub mod args;
2pub mod cmd;
3
4use std::process::ExitCode;
5pub type CliResult<T> = Result<T, Error>;
6
7use crate::{
8 core::{bootstrap::build_app_context, exit_code, report_error},
9 engine::{Error, ErrorCode},
10};
11use clap::Parser;
12use tracing::Level;
13use tracing_subscriber::{EnvFilter, fmt};
14
15pub fn run() -> ExitCode {
16 match tokio::runtime::Builder::new_multi_thread()
17 .enable_all()
18 .build()
19 {
20 Ok(runtime) => runtime.block_on(async_run()),
21 Err(err) => {
22 let err = ErrorCode::ProcessFailure
23 .error()
24 .with_context_str("runtime", err);
25
26 report_error(&err);
27 exit_code(&err)
28 }
29 }
30}
31
32async fn async_run() -> ExitCode {
33 let cli = args::Cli::parse();
34
35 let default_level = match (cli.global.verbose, cli.global.quiet) {
36 (_, q) if q >= 2 => Level::ERROR,
37 (_, 1) => Level::WARN,
38 (1, _) => Level::INFO,
39 (2, _) => Level::DEBUG,
40 (v, _) if v >= 3 => Level::TRACE,
41 _ => Level::WARN,
42 };
43 let filter = EnvFilter::try_from_default_env()
44 .unwrap_or_else(|_| EnvFilter::new(default_level.as_str()));
45 fmt()
46 .with_env_filter(filter)
47 .with_writer(std::io::stderr)
48 .init();
49
50 let ctx = match build_app_context(cli.global.into()) {
51 Ok(ctx) => ctx,
52 Err(err) => {
53 let err = ErrorCode::ProcessFailure
54 .error()
55 .with_context_str("app_context", err);
56 report_error(&err);
57 return exit_code(&err);
58 }
59 };
60
61 let result = match cli.command {
62 args::Command::Add(args) => cmd::add::run(&ctx, args).await,
63 args::Command::Bump(args) => cmd::bump::run(&ctx, args).await,
64 args::Command::Check(args) => cmd::check::run(&ctx, args).await,
65 args::Command::Commit(args) => cmd::commit::run(&ctx, args).await,
66 args::Command::Config(args) => cmd::config::run(&ctx, args).await,
67 args::Command::Doctor(args) => cmd::doctor::run(&ctx, args).await,
68 args::Command::Init(args) => cmd::init::run(&ctx, args).await,
69 args::Command::Push(args) => cmd::push::run(&ctx, args).await,
70 args::Command::Tag(args) => cmd::tag::run(&ctx, args).await,
71 };
72
73 if let Err(err) = result {
74 return exit_code(&err);
75 }
76
77 ExitCode::SUCCESS
78}