#![warn(missing_docs)]
mod commands;
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
use tga::core::config::Config;
use tga::core::db::Database;
#[derive(Parser, Debug)]
#[command(
name = "tga",
about = "trusty-git-analytics — developer productivity analytics",
version,
propagate_version = true
)]
struct Cli {
#[arg(short, long, default_value = "config.yaml", global = true)]
config: PathBuf,
#[arg(short, long, default_value = "tga.db", global = true)]
database: PathBuf,
#[arg(short, long, action = clap::ArgAction::Count, global = true)]
verbose: u8,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
Analyze(AnalyzeArgs),
Collect(CollectArgs),
Classify(ClassifyArgs),
Report(ReportArgs),
}
#[derive(Args, Debug)]
pub struct AnalyzeArgs {
#[arg(long)]
pub skip_collect: bool,
#[arg(long)]
pub skip_classify: bool,
#[arg(short, long)]
pub output: Option<PathBuf>,
}
#[derive(Args, Debug)]
pub struct CollectArgs {
#[arg(long, value_delimiter = ',')]
pub repos: Vec<String>,
#[arg(long)]
pub since: Option<String>,
#[arg(long)]
pub until: Option<String>,
}
#[derive(Args, Debug)]
pub struct ClassifyArgs {
#[arg(long)]
pub rules: Option<PathBuf>,
#[arg(long)]
pub use_llm: bool,
}
#[derive(Args, Debug)]
pub struct ReportArgs {
#[arg(short, long)]
pub output: Option<PathBuf>,
#[arg(long, value_delimiter = ',')]
pub formats: Vec<String>,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
let level = match cli.verbose {
0 => tracing::Level::WARN,
1 => tracing::Level::INFO,
2 => tracing::Level::DEBUG,
_ => tracing::Level::TRACE,
};
tracing_subscriber::fmt().with_max_level(level).init();
let config = if cli.config.exists() {
tracing::info!(path = %cli.config.display(), "loading config");
Config::load(&cli.config)?
} else {
tracing::warn!(
"config file {} not found, using defaults",
cli.config.display()
);
Config::default()
};
tracing::info!(path = %cli.database.display(), "opening database");
let mut db = Database::open(&cli.database)?;
match cli.command {
Commands::Analyze(args) => commands::analyze::run(config, &mut db, args).await?,
Commands::Collect(args) => commands::collect::run(config, &mut db, args).await?,
Commands::Classify(args) => commands::classify::run(config, &mut db, args).await?,
Commands::Report(args) => commands::report::run(config, &db, args)?,
}
Ok(())
}