Files
pile/crates/pile/src/main.rs
2026-03-16 09:56:48 -07:00

116 lines
2.5 KiB
Rust

use anyhow::{Context, Result};
use clap::Parser;
use config::LoggingPreset;
use indicatif::MultiProgress;
use pile_toolbox::cancelabletask::CancelableTaskResult;
use std::process::ExitCode;
use tracing::{error, warn};
use tracing_indicatif::{IndicatifWriter, writer::Stderr};
use tracing_subscriber::fmt::MakeWriter;
use crate::{
command::{CliCmd, CliCmdDispatch, SubCommand},
signal::start_signal_task,
};
mod cli;
mod command;
mod config;
mod signal;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None, styles=cli::clap_styles())]
struct Cli {
/// Increase verbosity (can be repeated)
#[arg(short, action = clap::ArgAction::Count,global = true)]
v: u8,
/// Decrease verbosity (can be repeated)
#[arg(short, action = clap::ArgAction::Count, global = true)]
q: u8,
#[command(subcommand)]
cmd: SubCommand,
}
#[derive(Clone)]
pub struct GlobalContext {
pub mp: MultiProgress,
}
fn main() -> ExitCode {
#[expect(clippy::unwrap_used)]
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.worker_threads(10)
.build()
.unwrap();
match rt.block_on(main_inner()) {
Ok(code) => {
std::process::exit(code);
}
Err(err) => {
for e in err.chain() {
error!("{}", e);
}
std::process::exit(1);
}
}
}
async fn main_inner() -> Result<i32> {
let cli = Cli::parse();
let level_i: i16 = cli.v as i16 - cli.q as i16;
let level;
if level_i <= -2 {
level = LoggingPreset::Error
} else if level_i == -1 {
level = LoggingPreset::Warn
} else if level_i == 0 {
level = LoggingPreset::Info
} else if level_i == 1 {
level = LoggingPreset::Debug
} else if level_i >= 2 {
level = LoggingPreset::Trace
} else {
unreachable!()
}
let mp = MultiProgress::new();
let writer: IndicatifWriter<Stderr> = IndicatifWriter::new(mp.clone());
tracing_subscriber::fmt()
.with_env_filter(level.get_config())
.without_time()
.with_ansi(true)
.with_writer(writer.make_writer())
.init();
let ctx = GlobalContext { mp };
let task = cli.cmd.start(ctx).context("while starting task")?;
let signal_task = start_signal_task(task.flag().clone());
match task.join().await {
Ok(CancelableTaskResult::Finished(Ok(code))) => Ok(code),
Ok(CancelableTaskResult::Cancelled) => {
signal_task.abort();
warn!("Task cancelled successfully");
Ok(1)
}
Err(err) => {
signal_task.abort();
Err(err).context("while joining task")
}
Ok(CancelableTaskResult::Finished(Err(err))) => {
signal_task.abort();
Err(err).context("while running task")
}
}
}