multimr 0.1.0

Create identical MR/PRs on multiple repositories.
//! The main entry point for the Multi MR TUI application.
use clap::Parser;

mod app;
mod config;
mod merge_request;
mod utils;

/// CLI arguments
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
    /// Run in dry-run mode (do not actually create MRs)
    #[arg(long)]
    dry_run: bool,
    /// Overwrite the assignee specified in multimr.toml
    #[arg(long)]
    assignee: Option<String>,
}

fn main() -> color_eyre::Result<()> {
    color_eyre::install()?; // setup error handling

    let cli = Cli::parse(); // parse the cli first so the user can always run --help or --version

    utils::ensure_glab_installed(); // Without `glab-cli` installed we cannot create merge requests, crash early

    let mut cfg = config::load_config_from_toml();

    // Overwrite configuration if provided via CLI
    if let Some(assignee) = cli.assignee {
        cfg.assignee = Some(assignee);
    }
    cfg.dry_run = cli.dry_run; // Set dry_run mode based on CLI argument

    // The interactive TUI app
    let terminal = ratatui::init();
    let app = app::App::new(cfg.clone());
    let app = app.run(terminal)?;

    ratatui::restore(); // restore state of terminal to what it was before the app started

    // If the user exited early, we just exit without doing anything
    if !app.user_input_completed {
        println!("Exiting without creating merge requests.");
        return Ok(());
    }

    run_commands(cfg.dry_run, app);

    Ok(())
}

/// Runs the commands generated by the app
fn run_commands(dry_run: bool, app: app::App) {
    println!("Multi MR will now create merge requests for the following repositories:");
    for dir_index in &app.selected_repos {
        println!(" - {}", app.dirs[*dir_index]);
    }

    for dir_index in app.selected_repos {
        let dir = app.dirs[dir_index].clone();
        std::env::set_current_dir(app.config.working_dir.join(&dir))
            .unwrap_or_else(|_| panic!("Failed to change directory to: {}", dir));

        let cmd = app.mr.as_ref().expect("somehow no mr specified").create();

        if dry_run {
            app.mr
                .as_ref()
                .expect("somehow no mr specified")
                .dry_run(cmd);
        } else {
            app.mr.as_ref().expect("somehow no mr specified").run(cmd);
        }
    }
}

#[cfg(test)]
mod test_main;