use std::path::PathBuf;
use anyhow::{Result, bail};
use clap::Subcommand;
use crate::cli_support::parse_schema_or_render;
mod lock_cmd;
mod reports;
use reports::{digest_report, print_report};
#[cfg(test)]
mod tests;
#[cfg(test)]
mod tests_lock;
#[derive(Debug, Subcommand)]
pub(crate) enum ContractAction {
Digest {
#[arg(long)]
schema: PathBuf,
#[arg(long)]
json: bool,
},
Print {
#[arg(long)]
schema: PathBuf,
#[arg(long)]
op: String,
},
Lock {
#[arg(long)]
schema: PathBuf,
#[arg(long)]
lock: PathBuf,
#[arg(long, default_value = "")]
note: String,
#[arg(long)]
date: Option<String>,
},
Check {
#[arg(long)]
schema: PathBuf,
#[arg(long)]
lock: PathBuf,
#[arg(long)]
json: bool,
},
#[command(group(clap::ArgGroup::new("what").required(true).multiple(false)))]
Prune {
#[arg(long)]
lock: PathBuf,
#[arg(long, group = "what")]
op: Option<String>,
#[arg(long, group = "what")]
before: Option<String>,
#[arg(long, group = "what")]
keep: Option<usize>,
#[arg(long, group = "what")]
generation: Option<String>,
},
}
pub(crate) fn run(action: ContractAction) -> Result<()> {
dispatch(action).or_else(|error| {
eprintln!("error: {error:#}");
std::process::exit(2)
})
}
fn dispatch(action: ContractAction) -> Result<()> {
match action {
ContractAction::Digest { schema, json } => {
print!(
"{}",
digest_report(&parse_schema_or_render(&schema)?, json)?
);
Ok(())
}
ContractAction::Print { schema, op } => {
println!("{}", print_report(&parse_schema_or_render(&schema)?, &op)?);
Ok(())
}
ContractAction::Lock {
schema,
lock,
note,
date,
} => {
let date = date.unwrap_or_else(|| chrono::Utc::now().format("%Y-%m-%d").to_string());
finish(lock_cmd::lock(
&parse_schema_or_render(&schema)?,
&lock,
¬e,
&date,
)?)
}
ContractAction::Check { schema, lock, json } => {
let schema = match parse_schema_or_render(&schema) {
Ok(schema) => schema,
Err(error) if json => return finish(lock_cmd::json_tool_error(&error, None)),
Err(error) => return Err(error),
};
finish(lock_cmd::check(&schema, &lock, json)?)
}
ContractAction::Prune {
lock,
op,
before,
keep,
generation,
} => {
let what = match (op, before, keep, generation) {
(Some(op), ..) => lock_cmd::Prune::Op(op),
(_, Some(date), ..) => lock_cmd::Prune::Before(date),
(_, _, Some(keep), _) => lock_cmd::Prune::Keep(keep),
(.., Some(prefix)) => lock_cmd::Prune::Generation(prefix),
_ => bail!("give one of --op, --before, --keep, --generation"),
};
finish(lock_cmd::prune(&lock, what)?)
}
}
}
fn finish(outcome: lock_cmd::Outcome) -> Result<()> {
print!("{}", outcome.text);
match outcome.exit_code() {
0 => Ok(()),
code => std::process::exit(code),
}
}