use clap::{Args, Parser, Subcommand};
use ctl_core::{ColorLong, DryRunArgs, FormatArgs};
use std::path::PathBuf;
#[derive(Parser)]
#[command(
version,
about = "Stack-agnostic version PRs from Changesets-format fragments",
arg_required_else_help = true
)]
pub struct Cli {
#[command(flatten)]
pub format: FormatArgs,
#[command(flatten)]
pub color: ColorLong,
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand)]
pub enum Command {
Instructions,
Status(StatusArgs),
Check(StatusArgs),
Prepare(PrepareArgs),
Publish(PublishArgs),
}
#[derive(Args)]
pub struct PublishArgs {
#[arg(short = 'c', long, default_value = "verctl.toml", value_hint = clap::ValueHint::FilePath)]
pub config: PathBuf,
#[command(flatten)]
pub dry: DryRunArgs,
}
impl PublishArgs {
#[must_use]
pub fn dry_run(&self) -> bool {
self.dry.dry_run
}
}
#[derive(Args)]
pub struct StatusArgs {
#[arg(short = 'd', long, default_value = ".changeset", value_hint = clap::ValueHint::DirPath)]
pub dir: PathBuf,
}
#[derive(Args)]
pub struct PrepareArgs {
#[arg(short = 'd', long, default_value = ".changeset", value_hint = clap::ValueHint::DirPath)]
pub dir: PathBuf,
#[arg(short = 'c', long, default_value = "verctl.toml", value_hint = clap::ValueHint::FilePath)]
pub config: PathBuf,
#[command(flatten)]
pub dry: DryRunArgs,
#[arg(long, overrides_with = "no_pr")]
pub pr: bool,
#[arg(long, overrides_with = "pr")]
pub no_pr: bool,
}
impl PrepareArgs {
#[must_use]
pub fn open_pr(&self) -> bool {
self.pr
}
#[must_use]
pub fn dry_run(&self) -> bool {
self.dry.dry_run
}
}
#[cfg(test)]
mod tests {
use super::{Cli, Command};
use clap::Parser;
fn prepare_from(args: &[&str]) -> super::PrepareArgs {
let mut words = vec!["verctl", "prepare"];
words.extend_from_slice(args);
match Cli::try_parse_from(words).expect("parse") {
Cli {
command: Command::Prepare(args),
..
} => args,
_ => panic!("expected prepare"),
}
}
#[test]
fn prepare_defaults_to_local() {
let args = prepare_from(&[]);
assert!(!args.open_pr());
assert!(!args.no_pr);
assert!(!args.pr);
}
#[test]
fn prepare_no_pr_is_local() {
let args = prepare_from(&["--no-pr"]);
assert!(!args.open_pr());
assert!(args.no_pr);
}
#[test]
fn prepare_pr_is_settable() {
let args = prepare_from(&["--pr"]);
assert!(args.open_pr());
assert!(args.pr);
assert!(!args.no_pr);
}
#[test]
fn last_pr_flag_wins() {
assert!(!prepare_from(&["--pr", "--no-pr"]).open_pr());
assert!(prepare_from(&["--no-pr", "--pr"]).open_pr());
}
#[test]
fn preview_is_dry_run() {
assert!(prepare_from(&["--preview"]).dry_run());
assert!(prepare_from(&["--dry-run"]).dry_run());
assert!(prepare_from(&["-n"]).dry_run());
}
}