use ::std::fmt;
use ::std::path::PathBuf;
use ::std::str::FromStr;
use ::clap::StructOpt;
use ::clap::ValueEnum;
use ::regex::Regex;
use crate::java::newtype::{FullyQualifiedName, Profile};
#[derive(StructOpt, Debug, Clone)]
#[structopt(
name = "java",
about = "Wrapper for maven (daemon) to add speed flags. Needs maven and uses git.",
after_help = "Thanks for using! Note: some options are only visible with --help (not with -h).",
group = clap::ArgGroup::new("test").multiple(false),
)]
pub struct MvnwArgs {
#[structopt(short = 'c', long)]
pub clean: bool,
#[structopt(short = 'i', long)]
pub install: bool,
#[structopt(short = 'a', long)]
pub all: bool,
#[structopt(short = 'U', long)]
pub update: bool,
#[structopt(short = 'm', long = "exec-main")]
pub execs: Vec<FullyQualifiedName>,
#[structopt(long = "test-files", group = "test")]
test_files: bool,
#[structopt(short = 't', long = "test-modules", group = "test")]
test_modules: bool,
#[structopt(long = "test-all", group = "test")]
test_all: bool,
#[structopt(long = "test-none", group = "test")]
test_none: bool,
#[structopt(short = 'T', long = "prod-only", group = "test")]
prod_only: bool,
#[structopt(short = 'L', long = "no-lint")]
pub no_lint: bool,
#[structopt(short = 'v', long)]
pub verbose: bool,
#[structopt(short = 'V', long, hide_short_help = true)]
pub show_cmds_only: bool,
#[structopt(
value_enum,
short = 'x',
long = "affected",
default_value = "recent",
conflicts_with = "all"
)]
pub affected_policy: AffectedPolicy,
#[structopt(long, validator = strictly_positive, hide_short_help = true)]
pub threads: Option<u32>,
#[structopt(long = "max-memory", validator = strictly_positive, default_value = "8192", hide_short_help = true)]
pub max_memory_mb: u32,
#[structopt(long = "max-exec-memory", validator = strictly_positive, hide_short_help = true)]
pub max_exec_memory_mb: Option<u32>,
#[structopt(long, default_value = "mvn", hide_short_help = true)]
pub mvn_exe: PathBuf,
#[structopt(long = "mvn-arg", hide_short_help = true)]
pub mvn_args: Vec<String>,
#[structopt(short = 'P', long = "profile")]
pub profiles: Vec<Profile>,
#[structopt(long = "proj-root", hide_short_help = true)]
pub proj_roots: Vec<PathBuf>,
#[structopt(short = 'C', long = "rebuild-if-match", hide_short_help = true)]
pub rebuild_if_match: Vec<Regex>,
#[structopt(short = 'g', long = "fail-if-added", hide_short_help = true)]
pub fail_if_added: Vec<Regex>,
}
fn strictly_positive(val: &str) -> Result<u32, String> {
match val.parse::<u32>() {
Ok(nr) => {
if nr >= 1 {
Ok(nr)
} else {
Err("must be at least 1".to_owned())
}
}
Err(err) => Err(err.to_string()),
}
}
#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
pub enum AffectedPolicy {
AnyChange,
Recent,
Uncommitted,
Head,
Branch,
}
impl FromStr for AffectedPolicy {
type Err = String;
fn from_str(text: &str) -> Result<Self, Self::Err> {
Ok(match text.to_lowercase().as_str() {
"a" | "any-change" | "all" => AffectedPolicy::AnyChange,
"r" | "recent" => AffectedPolicy::Recent,
"u" | "uncommitted" => AffectedPolicy::Uncommitted,
"h" | "head" => AffectedPolicy::Head,
"b" | "branch" => AffectedPolicy::Branch,
other => return Err(format!("unknown changed files policy: {}", other)),
})
}
}
impl fmt::Display for AffectedPolicy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
AffectedPolicy::AnyChange => "any-change",
AffectedPolicy::Recent => "recent",
AffectedPolicy::Uncommitted => "uncommitted",
AffectedPolicy::Head => "head",
AffectedPolicy::Branch => "branch",
}
)
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub enum TestMode {
#[default]
Files,
Modules,
All,
NoRun,
NoBuild,
}
impl TestMode {
pub fn run_any(&self) -> bool {
*self != TestMode::NoRun && *self != TestMode::NoBuild
}
}
impl MvnwArgs {
pub fn test(&self) -> TestMode {
match (
self.test_files,
self.test_modules,
self.test_all,
self.test_none,
self.prod_only,
) {
(true, false, false, false, false) => TestMode::Files,
(false, false, false, false, false) => TestMode::Files,
(false, true, false, false, false) => TestMode::Modules,
(false, false, true, false, false) => TestMode::All,
(false, false, false, true, false) => TestMode::NoRun,
(false, false, false, false, true) => TestMode::NoBuild,
_ => unreachable!("mutually exclusive arguments provided, CLI should prevent this"),
}
}
pub fn is_test_arg_provided(&self) -> bool {
!matches!(
(
self.test_files,
self.test_modules,
self.test_all,
self.test_none,
),
(false, false, false, false)
)
}
}
#[test]
fn test_cli_args() {
use clap::IntoApp;
MvnwArgs::into_app().debug_assert()
}