mod check;
mod diff;
mod edit;
mod init;
mod interactive;
mod query;
mod report;
use std::env;
use std::error::Error;
use std::io;
use std::path::PathBuf;
use std::process::ExitCode;
use clap::Subcommand;
use sara_core::config::Config;
use sara_core::model::Item;
use sara_core::repository::{GitReader, GitRef, parse_repositories};
use self::check::CheckArgs;
use self::diff::DiffArgs;
use self::edit::EditArgs;
use self::init::InitArgs;
use self::query::QueryArgs;
use self::report::ReportArgs;
use crate::Cli;
fn resolve_repositories(config: &Config) -> Result<Vec<PathBuf>, io::Error> {
if config.repositories.paths.is_empty() {
Ok(vec![env::current_dir()?])
} else {
Ok(config.repositories.paths.clone())
}
}
fn parse_items(config: &Config) -> Result<Vec<Item>, Box<dyn Error>> {
let repos = resolve_repositories(config)?;
Ok(parse_repositories(&repos)?)
}
fn parse_items_at(config: &Config, git_ref: &str) -> Result<Vec<Item>, Box<dyn Error>> {
let repos = resolve_repositories(config)?;
let git_ref = GitRef::parse(git_ref);
let mut all_items = Vec::new();
for repo_path in &repos {
if !repo_path.exists() {
tracing::warn!("Repository path does not exist: {}", repo_path.display());
continue;
}
let reader = GitReader::open(repo_path)?;
let items = reader.parse_commit(&git_ref)?;
all_items.extend(items);
}
Ok(all_items)
}
#[derive(Subcommand, Debug)]
#[command(disable_help_subcommand = true)]
pub enum Commands {
Check(CheckArgs),
Diff(DiffArgs),
Edit(EditArgs),
Init(InitArgs),
Query(QueryArgs),
Report(ReportArgs),
}
fn get_repositories(cli: &Cli, file_config: Option<&Config>) -> Result<Vec<PathBuf>, io::Error> {
if !cli.repository.is_empty() {
Ok(cli.repository.clone())
} else if let Some(config) = file_config {
if !config.repositories.paths.is_empty() {
Ok(config.repositories.paths.clone())
} else {
Ok(vec![env::current_dir()?])
}
} else {
Ok(vec![env::current_dir()?])
}
}
fn build_config(cli: &Cli, file_config: Option<&Config>) -> Result<Config, io::Error> {
let mut config = file_config.cloned().unwrap_or_default();
config.repositories.paths = get_repositories(cli, file_config)?;
config.output = cli.output_config(file_config);
Ok(config)
}
pub fn run(cli: &Cli, file_config: Option<&Config>) -> Result<ExitCode, Box<dyn Error>> {
let config = build_config(cli, file_config)?;
match &cli.command {
Commands::Check(args) => check::run(args, &config),
Commands::Diff(args) => diff::run(args, &config),
Commands::Edit(args) => edit::run(args, &config),
Commands::Init(args) => init::run(args, &config),
Commands::Query(args) => query::run(args, &config),
Commands::Report(args) => report::run(args, &config),
}
}