use std::ffi::OsString;
use clap::{Parser, Subcommand};
use nextsv::{CalculatorConfig, ForceBump, Hierarchy};
use proc_exit::{Code, ExitResult};
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Cli {
#[clap(flatten)]
logging: clap_verbosity_flag::Verbosity,
#[command(subcommand)]
command: Commands,
#[arg(short = 'b', long)]
no_bump: bool,
#[arg(short = 'n', long)]
number: bool,
#[clap(short, long)]
check: Option<Hierarchy>,
}
#[derive(Subcommand, Debug)]
enum Commands {
#[clap(name = "calculate", about = "Calculate the next version number")]
Calculate(Calculate),
#[clap(name = "force", about = "Force the bump level")]
Force(Force),
#[clap(
name = "require",
about = "Require the listed files to be updated before making a release with the specified change level"
)]
Require(Require),
}
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Calculate {
#[arg(short, long, value_parser, default_value = "v")]
prefix: String,
#[arg(short, long)]
subdir: Option<String>,
#[clap(short = 'k', long)]
pub package: Option<String>,
}
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Force {
#[command(subcommand)]
bump: ForceBump,
#[arg(short, long)]
first: bool,
#[arg(short, long, value_parser, default_value = "v")]
prefix: String,
}
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Require {
#[command(subcommand)]
enforce: Hierarchy,
#[arg(short, long)]
files: Vec<OsString>,
#[arg(short, long, value_parser, default_value = "v")]
prefix: String,
#[arg(short, long)]
subdir: Option<String>,
#[clap(short = 'k', long)]
pub package: Option<String>,
}
fn main() {
let result = run();
proc_exit::exit(result);
}
fn run() -> ExitResult {
let args = Cli::parse();
let mut builder = get_logging(args.logging.log_level_filter());
builder.init();
match (args.number, args.no_bump) {
(false, false) => log::info!("Calculating the next version level"),
(false, true) => log::info!("Calculating the next version level"),
(true, false) => log::info!("Calculating the next version number"),
(true, true) => log::info!("Calculating the next version number and level"),
};
let mut calculator_config = CalculatorConfig::new();
calculator_config = calculator_config.set_bump_report(!args.no_bump);
calculator_config = calculator_config.set_version_report(args.number);
if let Some(check_level) = args.check {
calculator_config = calculator_config.set_reporting_threshold(check_level);
};
match args.command {
Commands::Force(args) => {
calculator_config = calculator_config.set_prefix(&args.prefix);
calculator_config = calculator_config.set_force_bump(args.bump);
if args.first {
log::debug!("Setting first version and pre-release in the same transaction");
calculator_config = calculator_config.set_first_version();
};
}
Commands::Calculate(args) => {
calculator_config = calculator_config.set_prefix(&args.prefix);
calculator_config = calculator_config.set_subdir(args.subdir.as_deref());
calculator_config = calculator_config.set_package(args.package.as_deref());
}
Commands::Require(args) => {
calculator_config = calculator_config.set_prefix(&args.prefix);
calculator_config = calculator_config.set_subdir(args.subdir.as_deref());
calculator_config = calculator_config.set_package(args.package.as_deref());
calculator_config = calculator_config.add_required_files(args.files);
calculator_config = calculator_config.set_required_enforcement(args.enforce);
}
};
let calculator = calculator_config.build()?;
println!("{}", calculator.report());
Code::SUCCESS.ok()
}
fn get_logging(level: log::LevelFilter) -> env_logger::Builder {
let mut builder = env_logger::Builder::new();
builder.filter(None, level);
builder.format_timestamp_secs().format_module_path(false);
builder
}