use std::path::PathBuf;
use std::process::ExitCode;
use anyhow::Result;
use cargo_ratchet::{RatchetPaths, check_and_advance, check_fail_on_change};
use clap::Parser;
#[derive(Parser)]
#[command(name = "cargo", bin_name = "cargo")]
enum Cargo {
Ratchet(RatchetArgs),
}
#[derive(clap::Args)]
#[command(version, about)]
struct RatchetArgs {
#[arg(long)]
fail_on_change: bool,
#[arg(long)]
json: bool,
#[arg(long, value_name = "PATH")]
manifest_path: Option<PathBuf>,
#[arg(long, value_name = "PATH")]
lockfile: Option<PathBuf>,
#[arg(long, value_name = "PATH")]
ratchet_file: Option<PathBuf>,
}
fn main() -> Result<ExitCode> {
let Cargo::Ratchet(args) = Cargo::parse();
let paths = RatchetPaths::discover(
args.manifest_path.as_deref(),
args.lockfile,
args.ratchet_file,
)?;
if args.fail_on_change {
if check_fail_on_change(&paths)? {
return Ok(ExitCode::SUCCESS);
}
eprintln!(
"error: {} does not match {}; run `cargo ratchet` locally and commit the result",
paths.ratchet_file.display(),
paths.lockfile.display()
);
return Ok(ExitCode::FAILURE);
}
let violations = check_and_advance(&paths)?;
if violations.is_empty() {
return Ok(ExitCode::SUCCESS);
}
if args.json {
println!("{}", serde_json::to_string_pretty(&violations)?);
} else {
for violation in &violations {
eprintln!("error: {violation}");
}
}
Ok(ExitCode::FAILURE)
}