mod expr;
mod features;
pub(crate) mod substitutions;
pub use self::expr::*;
pub use self::features::FeatureSet;
pub use self::substitutions::{
InvalidSubstitutionPatternError, ScopedSubstitutionSet, SubstitutionSet,
};
use std::path::PathBuf;
use clap::Args;
use regex::Regex;
pub type Variable = litcheck::variables::Variable<String, String>;
#[derive(Debug, Args)]
pub struct Config {
#[arg(value_name = "TESTS", required(true), trailing_var_arg(true))]
pub tests: Vec<String>,
#[arg(long, short = 'j', value_name = "N")]
pub workers: Option<usize>,
#[arg(long = "param", short = 'D', value_name = "NAME=[VALUE]")]
pub params: Vec<Variable>,
#[arg(long, short = 'q', default_value_t = false, help_heading = "Output")]
pub quiet: bool,
#[arg(long, short = 'v', default_value_t = false, help_heading = "Output")]
pub verbose: bool,
#[arg(
long = "show-all",
short = 'a',
default_value_t = false,
help_heading = "Output"
)]
pub all: bool,
#[arg(
long = "no-execute",
default_value_t = false,
help_heading = "Execution Options"
)]
pub no_execute: bool,
#[arg(
long = "path",
value_name = "PATH",
value_parser(canonical_path_parser()),
help_heading = "Execution Options"
)]
pub search_paths: Vec<PathBuf>,
#[arg(
long,
value_name = "N",
default_value = "0",
help_heading = "Execution Options"
)]
pub timeout: Option<u64>,
#[arg(long, env = "LIT_FILTER", help_heading = "Selection Options")]
pub filter: Option<Regex>,
#[arg(long, env = "LIT_FILTER_OUT", help_heading = "Selection Options")]
pub filter_out: Option<Regex>,
#[arg(
long,
value_parser(target_triple_parser()),
value_name = "TRIPLE",
help_heading = "Selection Options"
)]
pub target: Option<target_lexicon::Triple>,
}
impl Config {
pub fn new(tests: Vec<String>) -> Self {
Self {
tests,
workers: None,
params: vec![],
quiet: false,
verbose: false,
all: false,
no_execute: false,
search_paths: vec![],
timeout: None,
filter: None,
filter_out: None,
target: None,
}
}
pub fn is_selected(&self, name: &str) -> bool {
let is_selected = self
.filter
.as_ref()
.map(|filter| filter.is_match(name))
.unwrap_or(true);
let is_excluded = self
.filter_out
.as_ref()
.map(|filter_out| filter_out.is_match(name))
.unwrap_or(false);
is_selected && !is_excluded
}
pub fn host(&self) -> target_lexicon::Triple {
target_lexicon::Triple::host()
}
pub fn target(&self) -> target_lexicon::Triple {
self.target
.clone()
.unwrap_or_else(target_lexicon::Triple::host)
}
}
fn target_triple_parser() -> clap::builder::ValueParser {
use clap::{builder::ValueParser, error::ErrorKind, Error};
ValueParser::from(|s: &str| -> Result<target_lexicon::Triple, clap::Error> {
s.parse::<target_lexicon::Triple>().map_err(|err| {
Error::raw(
ErrorKind::ValueValidation,
format!("invalid target triple '{s}': {err}"),
)
})
})
}
fn canonical_path_parser() -> clap::builder::ValueParser {
use clap::{builder::ValueParser, error::ErrorKind, Error};
ValueParser::from(|s: &str| -> Result<PathBuf, clap::Error> {
let path = std::path::Path::new(s);
path.canonicalize().map_err(|err| {
Error::raw(
ErrorKind::ValueValidation,
format!("invalid path '{s}': {err}"),
)
})
})
}