1use std::path::PathBuf;
2
3use clap::{Args, Parser};
4use glob::Pattern;
5
6#[cfg(feature = "coveralls")]
7use crate::config::Ci;
8use crate::config::{Color, Mode, OutputFile, RunType, TraceEngine};
9
10#[derive(Debug, Parser)]
11#[command(name = "cargo-tarpaulin")]
12#[command(bin_name = "cargo")]
13#[command(author, version, about, long_about = None)]
14pub enum CargoTarpaulinCli {
15 Tarpaulin(TarpaulinCli),
16}
17
18impl CargoTarpaulinCli {
19 pub fn from_args() -> TarpaulinCli {
20 match TarpaulinCli::try_parse() {
21 Ok(tarpaulin_cli) => tarpaulin_cli,
22 Err(err) if !err.use_stderr() => err.exit(),
23 Err(_) => match CargoTarpaulinCli::parse() {
24 CargoTarpaulinCli::Tarpaulin(tarpaulin_cli) => tarpaulin_cli,
25 },
26 }
27 }
28}
29
30#[derive(Debug, Parser)]
31#[command(name = "tarpaulin")]
32#[command(author, version, about, long_about = None)]
33pub struct TarpaulinCli {
34 #[clap(flatten)]
35 pub print_flags: PrintFlagsArgs,
36 #[clap(flatten)]
37 pub config: ConfigArgs,
38}
39
40#[derive(Debug, Clone, Args)]
41pub struct ConfigArgs {
42 #[clap(flatten)]
43 pub logging: LoggingArgs,
44 #[clap(flatten)]
45 pub run_types: RunTypesArgs,
46
47 #[arg(long, value_name = "FILE")]
49 pub config: Option<PathBuf>,
50 #[arg(long)]
52 pub ignore_config: bool,
53 #[arg(long, value_name = "NAME", num_args = 0..)]
55 pub bin: Vec<String>,
56 #[arg(long, value_name = "NAME", num_args = 0..)]
58 pub example: Vec<String>,
59 #[arg(long, value_name = "NAME", num_args = 0..)]
61 pub test: Vec<String>,
62 #[arg(long, value_name = "NAME", num_args = 0..)]
64 pub bench: Vec<String>,
65 #[arg(long)]
67 pub no_fail_fast: bool,
68 #[arg(long, value_name = "NAME")]
70 pub profile: Option<String>,
71 #[arg(long)]
73 pub ignore_tests: bool,
74 #[arg(long)]
76 pub no_dead_code: bool,
77 #[arg(long)]
79 pub include_tests: bool,
80 #[arg(long)]
82 pub ignore_panics: bool,
83 #[arg(long)]
85 pub count: bool,
86 #[arg(long, short)]
88 pub ignored: bool,
89 #[arg(long, short)]
91 pub line: bool,
92 #[arg(long)]
94 pub skip_clean: bool,
95 #[arg(long)]
97 pub force_clean: bool,
98 #[arg(long, value_name = "PERCENTAGE")]
100 pub fail_under: Option<f64>,
101 #[arg(long, short)]
103 pub branch: bool,
104 #[arg(long, short)]
106 pub forward: bool,
107 #[arg(long, value_name = "KEY")]
109 pub coveralls: Option<String>,
110 #[arg(long, value_name = "URI")]
112 pub report_uri: Option<String>,
113 #[arg(long)]
115 pub no_default_features: bool,
116 #[arg(long, value_name = "FEATURES", num_args = 0..)]
118 pub features: Vec<String>,
119 #[arg(long)]
121 pub all_features: bool,
122 #[arg(long)]
124 pub all: bool,
125 #[arg(long)]
127 pub workspace: bool,
128 #[arg(long, short, alias = "package", value_name = "PACKAGE", num_args = 0..)]
130 pub packages: Vec<String>,
131 #[arg(long, short, value_name = "PACKAGE", num_args = 0..)]
133 pub exclude: Vec<String>,
134 #[arg(long, value_name = "FILE", num_args = 0..)]
136 pub exclude_files: Vec<Pattern>,
137 #[arg(long, value_name = "FILE", num_args = 0..)]
139 pub include_files: Vec<Pattern>,
140 #[arg(long, short, value_name = "SECONDS")]
142 pub timeout: Option<u64>,
143 #[arg(long, value_name = "SECONDS")]
145 pub post_test_delay: Option<u64>,
146 #[arg(long)]
148 pub follow_exec: bool,
149 #[arg(long)]
151 pub release: bool,
152 #[arg(long)]
154 pub no_run: bool,
155 #[arg(long)]
157 pub implicit_test_threads: bool,
158 #[arg(long)]
160 pub locked: bool,
161 #[arg(long)]
163 pub frozen: bool,
164 #[arg(long, value_name = "TRIPLE")]
166 pub target: Option<String>,
167 #[arg(long, value_name = "DIR")]
169 pub target_dir: Option<PathBuf>,
170 #[arg(long)]
172 pub offline: bool,
173 #[arg(long)]
175 pub avoid_cfg_tarpaulin: bool,
176 #[arg(long, short, value_name = "N")]
178 pub jobs: Option<usize>,
179 #[arg(long, value_name = "FLAGS")]
181 pub rustflags: Option<String>,
182 #[arg(long, value_name = "objects", num_args = 0..)]
184 pub objects: Vec<PathBuf>,
185 #[arg(short = 'Z', value_name = "FEATURES", num_args = 0..)]
187 pub unstable_features: Vec<String>,
188 #[arg(long, short, value_enum, value_name = "FMT", num_args = 0.., ignore_case = true)]
190 pub out: Vec<OutputFile>,
191 #[arg(long, value_enum, value_name = "ENGINE", ignore_case = true)]
193 pub engine: Option<TraceEngine>,
194 #[arg(long, value_name = "PATH")]
196 pub output_dir: Option<PathBuf>,
197 #[arg(long, value_enum, value_name = "CMD", ignore_case = true)]
199 pub command: Option<Mode>,
200 #[arg(long, short, value_name = "DIR")]
202 pub root: Option<PathBuf>,
203 #[arg(long, value_name = "PATH")]
205 pub manifest_path: Option<PathBuf>,
206 #[cfg(feature = "coveralls")]
207 #[arg(long, value_name = "SERVICE")]
209 pub ciserver: Option<Ci>,
210 #[arg(long)]
212 pub fail_immediately: bool,
213 #[arg(last = true)]
215 pub args: Vec<String>,
216}
217
218#[derive(Debug, Clone, Copy, Args)]
219pub struct LoggingArgs {
220 #[arg(long, value_enum, value_name = "WHEN", ignore_case = true)]
222 pub color: Option<Color>,
223 #[arg(long)]
225 pub debug: bool,
226 #[arg(long, short)]
228 pub verbose: bool,
229 #[arg(long)]
231 pub dump_traces: bool,
232 #[arg(long)]
234 pub stderr: bool,
235}
236
237#[derive(Debug, Clone, Copy, Args)]
238pub struct PrintFlagsArgs {
239 #[arg(long)]
241 pub print_rust_flags: bool,
242 #[arg(long)]
244 pub print_rustdoc_flags: bool,
245}
246
247#[derive(Debug, Clone, Args)]
248pub struct RunTypesArgs {
249 #[arg(long, value_enum, value_name = "TYPE", ignore_case = true)]
251 pub run_types: Vec<RunType>,
252 #[arg(long)]
254 pub benches: bool,
255 #[arg(long)]
257 pub doc: bool,
258 #[arg(long)]
260 pub all_targets: bool,
261 #[arg(long)]
263 pub lib: bool,
264 #[arg(long)]
266 pub bins: bool,
267 #[arg(long)]
269 pub examples: bool,
270 #[arg(long)]
272 pub tests: bool,
273}
274
275impl RunTypesArgs {
276 pub fn collect(self) -> Vec<RunType> {
277 let mut run_types = self.run_types;
278 if self.lib && !run_types.contains(&RunType::Lib) {
279 run_types.push(RunType::Lib);
280 }
281 if self.all_targets && !run_types.contains(&RunType::AllTargets) {
282 run_types.push(RunType::AllTargets);
283 }
284 if self.benches && !run_types.contains(&RunType::Benchmarks) {
285 run_types.push(RunType::Benchmarks);
286 }
287 if self.bins && !run_types.contains(&RunType::Bins) {
288 run_types.push(RunType::Bins);
289 }
290 if self.examples && !run_types.contains(&RunType::Examples) {
291 run_types.push(RunType::Examples);
292 }
293 if self.doc && !run_types.contains(&RunType::Doctests) {
294 run_types.push(RunType::Doctests);
295 }
296 if self.tests && !run_types.contains(&RunType::Tests) {
297 run_types.push(RunType::Tests);
298 }
299 run_types
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use clap::CommandFactory;
306
307 use super::CargoTarpaulinCli;
308
309 #[test]
310 fn verify_args() {
311 CargoTarpaulinCli::command().debug_assert()
312 }
313
314 #[test]
315 #[ignore = "Manual use only"]
316 fn show_help() {
317 let help = CargoTarpaulinCli::command().render_help();
318 println!("{help}");
319 }
320}