use camino::Utf8PathBuf;
use clap::{Parser, Subcommand};
use diesel_guard::output::OutputFormatter;
use diesel_guard::{Config, SafetyChecker};
use miette::{IntoDiagnostic, Result};
use std::fs;
use std::process::exit;
const CONFIG_TEMPLATE: &str = include_str!("../diesel-guard.toml.example");
#[derive(Parser)]
#[command(name = "diesel-guard")]
#[command(version, about = "Catch unsafe PostgreSQL migrations in Diesel before they take down production", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Check {
path: Utf8PathBuf,
#[arg(long, default_value = "text")]
format: String,
},
Init {
#[arg(long)]
force: bool,
},
}
fn main() -> Result<()> {
miette::set_hook(Box::new(|_| {
Box::new(
miette::MietteHandlerOpts::new()
.terminal_links(true)
.unicode(true)
.context_lines(3)
.build(),
)
}))?;
let cli = Cli::parse();
match cli.command {
Commands::Check { path, format } => {
let config = match Config::load() {
Ok(config) => config,
Err(e) => {
eprintln!("Warning: {}", e);
eprintln!("Using default configuration.");
Config::default()
}
};
let checker = SafetyChecker::with_config(config);
let results = checker.check_path(&path)?;
if results.is_empty() {
OutputFormatter::print_summary(0);
exit(0);
}
let total_violations: usize = results.iter().map(|(_, v)| v.len()).sum();
match format.as_str() {
"json" => {
println!("{}", OutputFormatter::format_json(&results));
}
_ => {
for (file_path, violations) in &results {
print!("{}", OutputFormatter::format_text(file_path, violations));
}
OutputFormatter::print_summary(total_violations);
}
}
if total_violations > 0 {
exit(1);
}
}
Commands::Init { force } => {
let config_path = Utf8PathBuf::from("diesel-guard.toml");
let file_existed = config_path.exists();
if file_existed && !force {
eprintln!("Error: diesel-guard.toml already exists in current directory");
eprintln!("Use --force to overwrite the existing file");
exit(1);
}
fs::write(&config_path, CONFIG_TEMPLATE)
.into_diagnostic()
.map_err(|e| miette::miette!("Failed to write config file: {}", e))?;
if file_existed {
println!("✓ Overwrote diesel-guard.toml");
} else {
println!("✓ Created diesel-guard.toml");
}
println!();
println!("Next steps:");
println!("1. Edit diesel-guard.toml to customize your configuration");
println!("2. Run 'diesel-guard check <path>' to check your migrations");
}
}
Ok(())
}