mod args;
mod backend;
mod backend_error;
mod commands;
mod config;
mod error;
mod payload;
mod profiles;
mod progress;
mod prompt;
mod render;
mod resolve;
mod uploads;
use clap::Parser;
use std::process::ExitCode;
const USAGE_EXIT_CODE: u8 = 2;
pub async fn main() -> ExitCode {
let cli = match args::Cli::try_parse() {
Ok(cli) => cli,
Err(error) => return render_parse_failure(&error),
};
let runtime = args::RuntimeBehavior::detect(&cli);
match commands::run(cli, runtime).await {
Ok(output) => match render::render_success(&output, runtime.json) {
Ok(()) if output.data.reports_failures() => ExitCode::FAILURE,
Ok(()) => ExitCode::SUCCESS,
Err(err) => {
let failure = commands::CommandFailure {
kind: output.kind,
profile: output.profile.clone(),
mode: output.mode,
error: Box::new(error::CliError::io(err)),
};
let _ = render::render_error(&failure, runtime.json);
ExitCode::FAILURE
}
},
Err(failure) => {
let _ = render::render_error(&failure, runtime.json);
ExitCode::FAILURE
}
}
}
fn render_parse_failure(error: &clap::Error) -> ExitCode {
if !error.use_stderr() {
error.print().ok();
return ExitCode::SUCCESS;
}
if !json_requested(std::env::args_os()) {
error.print().ok();
return ExitCode::from(USAGE_EXIT_CODE);
}
let failure = error::CliError::invalid_usage(error.render().to_string());
let _ = render::render_parse_error(&failure);
ExitCode::from(USAGE_EXIT_CODE)
}
fn json_requested(arguments: impl IntoIterator<Item = std::ffi::OsString>) -> bool {
for argument in arguments {
if argument == "--" {
return false;
}
if argument == "--json" {
return true;
}
}
false
}