hypcmp 0.3.2

Extension to run hyperfine with toml files w/ commit switches.
use clap::Parser;
use log::{debug, error, info, trace};
use std::process::Command;

mod cli;
mod core;
mod util;

fn main() -> std::io::Result<()> {
    let config = cli::Cli::parse();
    env_logger::Builder::new()
        .filter_level(config.verbose.log_level_filter())
        .init();
    debug!("Loaded configuration: {config:?}");

    util::hyperfine_installed()?;
    util::is_git_dirty()?;

    let c = core::Benchmark::from_config(config.config)?;
    trace!("Benchmark Setup: {c:#?}");

    let dir = tempfile::tempdir()?;
    debug!("Temporary Directory: {dir:?}");

    let mut files_to_be_merged: Vec<String> = Vec::new();
    let current_branch = util::get_current_branch_or_id()?;
    info!("Current branch is: {current_branch:?}");

    for (label, run) in c.run.iter() {
        debug!("Run: {run:?}");

        let mut cmd = Command::new("hyperfine");
        cmd.args(c.to_hyperfine_params());

        let mut name = vec!["--command-name".to_string()];
        name.push(label.clone());
        cmd.args(name);

        let mut json = vec!["--export-json".to_string()];
        let mut filename = label.clone();
        filename.push_str(".json");
        let output = dir.path().join(filename).display().to_string();
        json.push(output.clone());
        cmd.args(json);

        cmd.args(run.to_hyperfine_params());
        info!("Running: {cmd:?}");

        let result = cmd.output()?;
        if result.status.success() {
            debug!("Benchmark run successful");
            files_to_be_merged.push(output);
        } else {
            let msg = result.stderr;
            let s = util::to_string(msg);
            error!("Run {label:?} failed. Skipping...");
            error!("Hyperfine message: {}", s);
            error!("Run parameters were: {cmd:?}");
        }
    }
    if files_to_be_merged.is_empty() {
        let msg = "No hyperfine benchmark run";
        error!("{msg}");
        let err = std::io::Error::new(std::io::ErrorKind::Other, msg);
        util::checkout(current_branch)?;
        return Err(err);
    } else {
        let json = util::merge_json_files(&files_to_be_merged)?;
        util::write_json_to_disk(json)?;
        util::cleanup(files_to_be_merged, dir)?;
        util::checkout(current_branch)?;
    }
    Ok(())
}