#![allow(clippy::collapsible_if)]
#![allow(clippy::derivable_impls)]
#![allow(clippy::type_complexity)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::unnecessary_map_or)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::manual_range_patterns)]
#![allow(clippy::ptr_arg)]
#![allow(clippy::single_char_add_str)]
#![allow(clippy::option_map_or_none)]
#![allow(clippy::match_like_matches_macro)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::filter_map_identity)]
mod args;
mod commands;
mod console;
mod router;
mod signal_handler;
mod ui;
use clap::Parser;
use sage_core::config::{load_config, load_config_from_file};
use sage_core::error::SageResult;
pub use args::{Cli, Commands, ConfigAction, DEFAULT_CONFIG_FILE};
fn try_fast_tools_subcommand() -> bool {
let mut args = std::env::args_os();
let _ = args.next();
let Some(first) = args.next() else {
return false;
};
if args.next().is_some() {
return false;
}
first == "tools"
}
fn try_fast_version_flag() -> bool {
let mut args = std::env::args_os();
let _ = args.next();
let Some(first) = args.next() else {
return false;
};
if args.next().is_some() {
return false;
}
if first == "--version" || first == "-V" {
println!("sage {}", env!("CARGO_PKG_VERSION"));
return true;
}
false
}
#[derive(Debug, Clone, Copy)]
enum LogFormat {
Json,
Pretty,
Compact,
}
fn resolve_log_format(cli: &Cli) -> LogFormat {
let config = if cli.config_file == args::DEFAULT_CONFIG_FILE {
load_config().ok()
} else {
load_config_from_file(&cli.config_file).ok()
};
match config.as_ref().map(|cfg| cfg.logging.format.as_str()) {
Some("json") => LogFormat::Json,
Some("pretty") => LogFormat::Pretty,
_ => LogFormat::Compact,
}
}
fn init_tracing(cli: &Cli) {
if std::env::var_os("RUST_LOG").is_none() {
return;
}
let env_filter = tracing_subscriber::EnvFilter::from_default_env();
match resolve_log_format(cli) {
LogFormat::Json => {
tracing_subscriber::fmt()
.json()
.with_env_filter(env_filter)
.with_writer(std::io::stderr)
.init();
}
LogFormat::Pretty => {
tracing_subscriber::fmt()
.pretty()
.with_env_filter(env_filter)
.with_writer(std::io::stderr)
.init();
}
LogFormat::Compact => {
tracing_subscriber::fmt()
.compact()
.with_env_filter(env_filter)
.with_writer(std::io::stderr)
.init();
}
}
}
fn try_sync_utility_command(cli: &Cli) -> Option<SageResult<()>> {
match &cli.command {
Some(Commands::Tools) => Some(commands::tools::show_tools_sync()),
Some(Commands::Config { action }) => match action {
ConfigAction::Show { config_file } => Some(commands::config::show_sync(config_file)),
ConfigAction::Validate { config_file } => {
Some(commands::config::validate_sync(config_file))
}
ConfigAction::Init { .. } => None,
},
_ => None,
}
}
async fn async_main(cli: Cli) -> SageResult<()> {
init_tracing(&cli);
router::route(cli).await
}
fn main() -> SageResult<()> {
if try_fast_version_flag() {
return Ok(());
}
if try_fast_tools_subcommand() {
return commands::tools::show_tools_sync();
}
let cli = Cli::parse();
if let Some(result) = try_sync_utility_command(&cli) {
return result;
}
tokio::runtime::Runtime::new()?.block_on(async_main(cli))
}