#![windows_subsystem = "windows"]
use std::path::PathBuf;
use clap::Parser;
use gio::prelude::ApplicationExtManual;
use gtk4::{Application, glib};
use mergers::{CompareMode, ui, vcs};
#[derive(Parser)]
#[command(name = "mergers", version, about = "Visual diff and merge tool")]
struct Cli {
paths: Vec<PathBuf>,
#[arg(short = 'L', long = "label")]
labels: Vec<String>,
}
fn main() -> glib::ExitCode {
let cli = Cli::parse();
let mode = if cli.paths.len() == 3 {
let left = &cli.paths[0];
let middle = &cli.paths[1];
let right = &cli.paths[2];
for p in [left, middle, right] {
if !p.is_file() {
eprintln!("Error: '{}' is not a file", p.display());
std::process::exit(1);
}
}
CompareMode::Merge {
left: left.clone(),
middle: middle.clone(),
right: right.clone(),
labels: cli.labels.clone(),
}
} else if cli.paths.len() == 2 {
let left = &cli.paths[0];
let right = &cli.paths[1];
if left.is_file() && right.is_file() {
CompareMode::Files {
left: left.clone(),
right: right.clone(),
labels: cli.labels.clone(),
}
} else if left.is_dir() && right.is_dir() {
CompareMode::Dirs {
left: left.clone(),
right: right.clone(),
labels: cli.labels.clone(),
}
} else if !left.exists() {
eprintln!("Error: '{}' does not exist", left.display());
std::process::exit(1);
} else if !right.exists() {
eprintln!("Error: '{}' does not exist", right.display());
std::process::exit(1);
} else {
eprintln!("Error: cannot compare a file with a directory");
std::process::exit(1);
}
} else if cli.paths.len() == 1 {
let path = &cli.paths[0];
if path.is_dir() && vcs::is_git_repo(path) {
CompareMode::Vcs { dir: path.clone() }
} else if path.is_dir() {
eprintln!("Error: '{}' is not inside a git repository", path.display());
eprintln!("For directory comparison, provide two directories.");
std::process::exit(1);
} else {
eprintln!("Error: single file argument not supported. Provide 2 files to compare.");
std::process::exit(1);
}
} else if cli.paths.is_empty() {
CompareMode::Welcome
} else {
eprintln!(
"Error: expected 0-3 paths, got {}. Usage: mergers [LEFT RIGHT] or [LEFT MIDDLE RIGHT]",
cli.paths.len()
);
std::process::exit(1);
};
let application = Application::builder().application_id("mergers").build();
ui::build_ui(&application, mode);
application.run_with_args::<String>(&[])
}