litcheck_lit/config/
mod.rs1mod expr;
2mod features;
3pub(crate) mod substitutions;
4
5pub use self::expr::*;
6pub use self::features::FeatureSet;
7pub use self::substitutions::{
8 InvalidSubstitutionPatternError, ScopedSubstitutionSet, SubstitutionSet,
9};
10
11use std::path::PathBuf;
12
13use clap::Args;
14use regex::Regex;
15
16pub type Variable = litcheck::variables::Variable<String, String>;
17
18#[derive(Debug, Args)]
19pub struct Config {
20 #[arg(value_name = "TESTS", required(true), trailing_var_arg(true))]
22 pub tests: Vec<String>,
23 #[arg(long, short = 'j', value_name = "N")]
27 pub workers: Option<usize>,
28 #[arg(long = "param", short = 'D', value_name = "NAME=[VALUE]")]
30 pub params: Vec<Variable>,
31 #[arg(long, short = 'q', default_value_t = false, help_heading = "Output")]
33 pub quiet: bool,
34 #[arg(long, short = 'v', default_value_t = false, help_heading = "Output")]
39 pub verbose: bool,
40 #[arg(
42 long = "show-all",
43 short = 'a',
44 default_value_t = false,
45 help_heading = "Output"
46 )]
47 pub all: bool,
48 #[arg(
53 long = "no-execute",
54 default_value_t = false,
55 help_heading = "Execution Options"
56 )]
57 pub no_execute: bool,
58 #[arg(
60 long = "path",
61 value_name = "PATH",
62 value_parser(canonical_path_parser()),
63 help_heading = "Execution Options"
64 )]
65 pub search_paths: Vec<PathBuf>,
66 #[arg(
70 long,
71 value_name = "N",
72 default_value = "0",
73 help_heading = "Execution Options"
74 )]
75 pub timeout: Option<u64>,
76 #[arg(long, env = "LIT_FILTER", help_heading = "Selection Options")]
78 pub filter: Option<Regex>,
79 #[arg(long, env = "LIT_FILTER_OUT", help_heading = "Selection Options")]
81 pub filter_out: Option<Regex>,
82 #[arg(
88 long,
89 value_parser(target_triple_parser()),
90 value_name = "TRIPLE",
91 help_heading = "Selection Options"
92 )]
93 pub target: Option<target_lexicon::Triple>,
94}
95impl Config {
96 pub fn new(tests: Vec<String>) -> Self {
97 Self {
98 tests,
99 workers: None,
100 params: vec![],
101 quiet: false,
102 verbose: false,
103 all: false,
104 no_execute: false,
105 search_paths: vec![],
106 timeout: None,
107 filter: None,
108 filter_out: None,
109 target: None,
110 }
111 }
112
113 pub fn is_selected(&self, name: &str) -> bool {
115 let is_selected = self
116 .filter
117 .as_ref()
118 .map(|filter| filter.is_match(name))
119 .unwrap_or(true);
120 let is_excluded = self
121 .filter_out
122 .as_ref()
123 .map(|filter_out| filter_out.is_match(name))
124 .unwrap_or(false);
125 is_selected && !is_excluded
126 }
127
128 pub fn host(&self) -> target_lexicon::Triple {
129 target_lexicon::Triple::host()
130 }
131
132 pub fn target(&self) -> target_lexicon::Triple {
133 self.target
134 .clone()
135 .unwrap_or_else(target_lexicon::Triple::host)
136 }
137}
138
139fn target_triple_parser() -> clap::builder::ValueParser {
140 use clap::{builder::ValueParser, error::ErrorKind, Error};
141 ValueParser::from(|s: &str| -> Result<target_lexicon::Triple, clap::Error> {
142 s.parse::<target_lexicon::Triple>().map_err(|err| {
143 Error::raw(
144 ErrorKind::ValueValidation,
145 format!("invalid target triple '{s}': {err}"),
146 )
147 })
148 })
149}
150
151fn canonical_path_parser() -> clap::builder::ValueParser {
152 use clap::{builder::ValueParser, error::ErrorKind, Error};
153 ValueParser::from(|s: &str| -> Result<PathBuf, clap::Error> {
154 let path = std::path::Path::new(s);
155 path.canonicalize().map_err(|err| {
156 Error::raw(
157 ErrorKind::ValueValidation,
158 format!("invalid path '{s}': {err}"),
159 )
160 })
161 })
162}