]> git.proxmox.com Git - rustc.git/blame - src/bootstrap/flags.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / src / bootstrap / flags.rs
CommitLineData
a7813a04
XL
1//! Command-line interface of the rustbuild build system.
2//!
3//! This module implements the command-line parsing of the build system which
4//! has various flags to configure how it's run.
5
f035d41b 6use std::env;
7453a54e
SL
7use std::path::PathBuf;
8use std::process;
7453a54e 9
cc61c64b 10use getopts::Options;
c30ab7b3 11
0731742a 12use crate::builder::Builder;
f035d41b 13use crate::cache::{Interned, INTERNER};
0731742a 14use crate::config::Config;
0731742a 15use crate::{Build, DocTests};
3b2f2976 16
a7813a04 17/// Deserialized version of all flags for this compile.
7453a54e 18pub struct Flags {
0531ce1d 19 pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo
8bb4bdeb 20 pub on_fail: Option<String>,
7453a54e 21 pub stage: Option<u32>,
8faf50e0 22 pub keep_stage: Vec<u32>,
3b2f2976
XL
23
24 pub host: Vec<Interned<String>>,
25 pub target: Vec<Interned<String>>,
7453a54e 26 pub config: Option<PathBuf>,
7453a54e 27 pub jobs: Option<u32>,
c30ab7b3 28 pub cmd: Subcommand,
32a655c1 29 pub incremental: bool,
2c00a5a8 30 pub exclude: Vec<PathBuf>,
0531ce1d 31 pub rustc_error_format: Option<String>,
ba9703b0 32 pub json_output: bool,
83c7162d
XL
33 pub dry_run: bool,
34
74b04a01 35 // This overrides the deny-warnings configuration option,
416331ca
XL
36 // which passes -Dwarnings to the compiler invocations.
37 //
e1599b0c 38 // true => deny, false => warn
416331ca 39 pub deny_warnings: Option<bool>,
dfeec247
XL
40
41 pub llvm_skip_rebuild: Option<bool>,
32a655c1
SL
42}
43
c30ab7b3
SL
44pub enum Subcommand {
45 Build {
46 paths: Vec<PathBuf>,
47 },
2c00a5a8
XL
48 Check {
49 paths: Vec<PathBuf>,
50 },
dc9dc135
XL
51 Clippy {
52 paths: Vec<PathBuf>,
53 },
54 Fix {
55 paths: Vec<PathBuf>,
56 },
dfeec247
XL
57 Format {
58 check: bool,
59 },
c30ab7b3
SL
60 Doc {
61 paths: Vec<PathBuf>,
f9f354fc 62 open: bool,
c30ab7b3
SL
63 },
64 Test {
65 paths: Vec<PathBuf>,
94b46f34
XL
66 /// Whether to automatically update stderr/stdout files
67 bless: bool,
68 compare_mode: Option<String>,
dc9dc135 69 pass: Option<String>,
c30ab7b3 70 test_args: Vec<String>,
2c00a5a8 71 rustc_args: Vec<String>,
041b39d2 72 fail_fast: bool,
83c7162d 73 doc_tests: DocTests,
532ac7d7 74 rustfix_coverage: bool,
c30ab7b3 75 },
476ff2be
SL
76 Bench {
77 paths: Vec<PathBuf>,
78 test_args: Vec<String>,
79 },
ea8adc8c
XL
80 Clean {
81 all: bool,
82 },
c30ab7b3 83 Dist {
32a655c1 84 paths: Vec<PathBuf>,
7cac9316
XL
85 },
86 Install {
87 paths: Vec<PathBuf>,
c30ab7b3 88 },
ba9703b0
XL
89 Run {
90 paths: Vec<PathBuf>,
91 },
7453a54e
SL
92}
93
3b2f2976
XL
94impl Default for Subcommand {
95 fn default() -> Subcommand {
dfeec247 96 Subcommand::Build { paths: vec![PathBuf::from("nowhere")] }
3b2f2976
XL
97 }
98}
99
7453a54e
SL
100impl Flags {
101 pub fn parse(args: &[String]) -> Flags {
cc61c64b 102 let mut extra_help = String::new();
dfeec247
XL
103 let mut subcommand_help = String::from(
104 "\
cc61c64b
XL
105Usage: x.py <subcommand> [options] [<paths>...]
106
107Subcommands:
f9f354fc
XL
108 build, b Compile either the compiler or libraries
109 check, c Compile either the compiler or libraries, using cargo check
dfeec247 110 clippy Run clippy (uses rustup/cargo-installed clippy binary)
dc9dc135 111 fix Run cargo fix
dfeec247 112 fmt Run rustfmt
f9f354fc 113 test, t Build and run some test suites
cc61c64b
XL
114 bench Build and run some benchmarks
115 doc Build documentation
116 clean Clean out build directories
7cac9316
XL
117 dist Build distribution artifacts
118 install Install distribution artifacts
f9f354fc 119 run, r Run tools contained in this repository
cc61c64b 120
dfeec247 121To learn more about a subcommand, run `./x.py <subcommand> -h`",
94b46f34 122 );
cc61c64b 123
7453a54e 124 let mut opts = Options::new();
cc61c64b 125 // Options common to all subcommands
32a655c1
SL
126 opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)");
127 opts.optflag("i", "incremental", "use incremental compilation");
7453a54e 128 opts.optopt("", "config", "TOML configuration file for build", "FILE");
c30ab7b3 129 opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
7453a54e 130 opts.optmulti("", "host", "host targets to build", "HOST");
c30ab7b3 131 opts.optmulti("", "target", "target targets to build", "TARGET");
2c00a5a8 132 opts.optmulti("", "exclude", "build paths to exclude", "PATH");
8bb4bdeb 133 opts.optopt("", "on-fail", "command to run on failure", "CMD");
83c7162d 134 opts.optflag("", "dry-run", "dry run; don't build anything");
dfeec247
XL
135 opts.optopt(
136 "",
137 "stage",
0731742a 138 "stage to build (indicates compiler to use/test, e.g., stage 0 uses the \
b7449926 139 bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
dfeec247
XL
140 "N",
141 );
142 opts.optmulti(
143 "",
144 "keep-stage",
145 "stage(s) to keep without recompiling \
146 (pass multiple times to keep e.g., both stages 0 and 1)",
147 "N",
148 );
c30ab7b3 149 opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
f035d41b
XL
150 let j_msg = format!(
151 "number of jobs to run in parallel; \
152 defaults to {} (this host's logical CPU count)",
153 num_cpus::get()
154 );
155 opts.optopt("j", "jobs", &j_msg, "JOBS");
7453a54e 156 opts.optflag("h", "help", "print this help message");
94b46f34
XL
157 opts.optopt(
158 "",
159 "warnings",
160 "if value is deny, will deny warnings, otherwise use default",
161 "VALUE",
162 );
0531ce1d 163 opts.optopt("", "error-format", "rustc error format", "FORMAT");
ba9703b0 164 opts.optflag("", "json-output", "use message-format=json");
dfeec247
XL
165 opts.optopt(
166 "",
167 "llvm-skip-rebuild",
168 "whether rebuilding llvm should be skipped \
169 a VALUE of TRUE indicates that llvm will not be rebuilt \
170 VALUE overrides the skip-rebuild option in config.toml.",
171 "VALUE",
172 );
7453a54e 173
cc61c64b 174 // fn usage()
94b46f34
XL
175 let usage =
176 |exit_code: i32, opts: &Options, subcommand_help: &str, extra_help: &str| -> ! {
177 println!("{}", opts.usage(subcommand_help));
178 if !extra_help.is_empty() {
179 println!("{}", extra_help);
180 }
181 process::exit(exit_code);
182 };
cc61c64b
XL
183
184 // We can't use getopt to parse the options until we have completed specifying which
185 // options are valid, but under the current implementation, some options are conditional on
186 // the subcommand. Therefore we must manually identify the subcommand first, so that we can
187 // complete the definition of the options. Then we can use the getopt::Matches object from
188 // there on out.
94b46f34 189 let subcommand = args.iter().find(|&s| {
041b39d2 190 (s == "build")
f9f354fc 191 || (s == "b")
94b46f34 192 || (s == "check")
f9f354fc 193 || (s == "c")
dc9dc135
XL
194 || (s == "clippy")
195 || (s == "fix")
dfeec247 196 || (s == "fmt")
94b46f34 197 || (s == "test")
f9f354fc 198 || (s == "t")
94b46f34
XL
199 || (s == "bench")
200 || (s == "doc")
201 || (s == "clean")
202 || (s == "dist")
203 || (s == "install")
ba9703b0 204 || (s == "run")
f9f354fc 205 || (s == "r")
94b46f34 206 });
041b39d2 207 let subcommand = match subcommand {
cc61c64b
XL
208 Some(s) => s,
209 None => {
abe05a73
XL
210 // No or an invalid subcommand -- show the general usage and subcommand help
211 // An exit code will be 0 when no subcommand is given, and 1 in case of an invalid
212 // subcommand.
cc61c64b 213 println!("{}\n", subcommand_help);
abe05a73
XL
214 let exit_code = if args.is_empty() { 0 } else { 1 };
215 process::exit(exit_code);
cc61c64b
XL
216 }
217 };
c30ab7b3 218
cc61c64b
XL
219 // Some subcommands get extra options
220 match subcommand.as_str() {
f9f354fc 221 "test" | "t" => {
7cac9316
XL
222 opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
223 opts.optmulti("", "test-args", "extra arguments", "ARGS");
2c00a5a8
XL
224 opts.optmulti(
225 "",
226 "rustc-args",
227 "extra options to pass the compiler when running tests",
228 "ARGS",
229 );
83c7162d
XL
230 opts.optflag("", "no-doc", "do not run doc tests");
231 opts.optflag("", "doc", "only run doc tests");
dfeec247 232 opts.optflag("", "bless", "update all stderr/stdout files of failing ui tests");
94b46f34
XL
233 opts.optopt(
234 "",
235 "compare-mode",
236 "mode describing what file the actual ui output will be compared to",
237 "COMPARE MODE",
238 );
dc9dc135
XL
239 opts.optopt(
240 "",
241 "pass",
242 "force {check,build,run}-pass tests to this mode.",
dfeec247 243 "check | build | run",
dc9dc135 244 );
532ac7d7
XL
245 opts.optflag(
246 "",
247 "rustfix-coverage",
248 "enable this to generate a Rustfix coverage file, which is saved in \
249 `/<build_base>/rustfix_missing_coverage.txt`",
250 );
94b46f34
XL
251 }
252 "bench" => {
253 opts.optmulti("", "test-args", "extra arguments", "ARGS");
254 }
f9f354fc
XL
255 "doc" => {
256 opts.optflag("", "open", "open the docs in a browser");
257 }
94b46f34
XL
258 "clean" => {
259 opts.optflag("", "all", "clean all build artifacts");
260 }
dfeec247
XL
261 "fmt" => {
262 opts.optflag("", "check", "check formatting instead of applying.");
263 }
94b46f34 264 _ => {}
cc61c64b
XL
265 };
266
267 // Done specifying what options are possible, so do the getopts parsing
268 let matches = opts.parse(&args[..]).unwrap_or_else(|e| {
269 // Invalid argument/option format
270 println!("\n{}\n", e);
271 usage(1, &opts, &subcommand_help, &extra_help);
272 });
273 // Extra sanity check to make sure we didn't hit this crazy corner case:
274 //
275 // ./x.py --frobulate clean build
276 // ^-- option ^ ^- actual subcommand
277 // \_ arg to option could be mistaken as subcommand
278 let mut pass_sanity_check = true;
279 match matches.free.get(0) {
280 Some(check_subcommand) => {
041b39d2 281 if check_subcommand != subcommand {
cc61c64b
XL
282 pass_sanity_check = false;
283 }
94b46f34 284 }
cc61c64b
XL
285 None => {
286 pass_sanity_check = false;
287 }
288 }
289 if !pass_sanity_check {
290 println!("{}\n", subcommand_help);
94b46f34
XL
291 println!(
292 "Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
293 You may need to move some options to after the subcommand.\n"
294 );
cc61c64b
XL
295 process::exit(1);
296 }
297 // Extra help text for some commands
298 match subcommand.as_str() {
f9f354fc 299 "build" | "b" => {
94b46f34
XL
300 subcommand_help.push_str(
301 "\n
c30ab7b3 302Arguments:
cc61c64b
XL
303 This subcommand accepts a number of paths to directories to the crates
304 and/or artifacts to compile. For example:
c30ab7b3
SL
305
306 ./x.py build src/libcore
cc61c64b 307 ./x.py build src/libcore src/libproc_macro
c30ab7b3
SL
308 ./x.py build src/libstd --stage 1
309
310 If no arguments are passed then the complete artifacts for that stage are
311 also compiled.
312
313 ./x.py build
314 ./x.py build --stage 1
315
041b39d2
XL
316 For a quick build of a usable compiler, you can pass:
317
318 ./x.py build --stage 1 src/libtest
c30ab7b3 319
b7449926 320 This will first build everything once (like `--stage 0` without further
041b39d2
XL
321 arguments would), and then use the compiler built in stage 0 to build
322 src/libtest and its dependencies.
94b46f34
XL
323 Once this is done, build/$ARCH/stage1 contains a usable compiler.",
324 );
2c00a5a8 325 }
f9f354fc 326 "check" | "c" => {
94b46f34
XL
327 subcommand_help.push_str(
328 "\n
2c00a5a8
XL
329Arguments:
330 This subcommand accepts a number of paths to directories to the crates
331 and/or artifacts to compile. For example:
332
333 ./x.py check src/libcore
334 ./x.py check src/libcore src/libproc_macro
335
336 If no arguments are passed then the complete artifacts are compiled: std, test, and rustc. Note
337 also that since we use `cargo check`, by default this will automatically enable incremental
338 compilation, so there's no need to pass it separately, though it won't hurt. We also completely
339 ignore the stage passed, as there's no way to compile in non-stage 0 without actually building
94b46f34
XL
340 the compiler.",
341 );
cc61c64b 342 }
dc9dc135
XL
343 "clippy" => {
344 subcommand_help.push_str(
345 "\n
346Arguments:
347 This subcommand accepts a number of paths to directories to the crates
348 and/or artifacts to run clippy against. For example:
349
350 ./x.py clippy src/libcore
351 ./x.py clippy src/libcore src/libproc_macro",
352 );
353 }
354 "fix" => {
355 subcommand_help.push_str(
356 "\n
357Arguments:
358 This subcommand accepts a number of paths to directories to the crates
359 and/or artifacts to run `cargo fix` against. For example:
360
361 ./x.py fix src/libcore
362 ./x.py fix src/libcore src/libproc_macro",
363 );
364 }
dfeec247
XL
365 "fmt" => {
366 subcommand_help.push_str(
367 "\n
368Arguments:
369 This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and
370 fails if it is not. For example:
371
372 ./x.py fmt
373 ./x.py fmt --check",
374 );
375 }
f9f354fc 376 "test" | "t" => {
94b46f34
XL
377 subcommand_help.push_str(
378 "\n
c30ab7b3 379Arguments:
ba9703b0 380 This subcommand accepts a number of paths to test directories that
cc61c64b 381 should be compiled and run. For example:
c30ab7b3 382
416331ca 383 ./x.py test src/test/ui
c30ab7b3 384 ./x.py test src/libstd --test-args hash_map
b7449926 385 ./x.py test src/libstd --stage 0 --no-doc
94b46f34
XL
386 ./x.py test src/test/ui --bless
387 ./x.py test src/test/ui --compare-mode nll
c30ab7b3 388
b7449926
XL
389 Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`;
390 just like `build src/libstd --stage N` it tests the compiler produced by the previous
391 stage.
392
ba9703b0
XL
393 Execute tool tests with a tool name argument:
394
395 ./x.py test tidy
396
c30ab7b3
SL
397 If no arguments are passed then the complete artifacts for that stage are
398 compiled and tested.
399
400 ./x.py test
94b46f34
XL
401 ./x.py test --stage 1",
402 );
cc61c64b
XL
403 }
404 "doc" => {
94b46f34
XL
405 subcommand_help.push_str(
406 "\n
c30ab7b3 407Arguments:
cc61c64b
XL
408 This subcommand accepts a number of paths to directories of documentation
409 to build. For example:
c30ab7b3
SL
410
411 ./x.py doc src/doc/book
412 ./x.py doc src/doc/nomicon
cc61c64b 413 ./x.py doc src/doc/book src/libstd
f9f354fc 414 ./x.py doc src/libstd --open
c30ab7b3
SL
415
416 If no arguments are passed then everything is documented:
417
418 ./x.py doc
94b46f34
XL
419 ./x.py doc --stage 1",
420 );
c30ab7b3 421 }
f9f354fc 422 "run" | "r" => {
ba9703b0
XL
423 subcommand_help.push_str(
424 "\n
425Arguments:
426 This subcommand accepts a number of paths to tools to build and run. For
427 example:
428
429 ./x.py run src/tool/expand-yaml-anchors
430
431 At least a tool needs to be called.",
432 );
433 }
94b46f34 434 _ => {}
7453a54e 435 };
cc61c64b 436 // Get any optional paths which occur after the subcommand
dfeec247 437 let paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
cc61c64b 438
f035d41b 439 let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
cc61c64b 440
ea8adc8c 441 // All subcommands except `clean` can have an optional "Available paths" section
cc61c64b 442 if matches.opt_present("verbose") {
3b2f2976 443 let config = Config::parse(&["build".to_string()]);
f035d41b 444 let build = Build::new(config);
3b2f2976
XL
445
446 let maybe_rules_help = Builder::get_help(&build, subcommand.as_str());
447 extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
dfeec247 448 } else if !(subcommand.as_str() == "clean" || subcommand.as_str() == "fmt") {
94b46f34 449 extra_help.push_str(
dfeec247
XL
450 format!("Run `./x.py {} -h -v` to see a list of available paths.", subcommand)
451 .as_str(),
94b46f34 452 );
cc61c64b 453 }
c30ab7b3 454
cc61c64b
XL
455 // User passed in -h/--help?
456 if matches.opt_present("help") {
457 usage(0, &opts, &subcommand_help, &extra_help);
458 }
c30ab7b3 459
cc61c64b 460 let cmd = match subcommand.as_str() {
f9f354fc
XL
461 "build" | "b" => Subcommand::Build { paths },
462 "check" | "c" => Subcommand::Check { paths },
dc9dc135
XL
463 "clippy" => Subcommand::Clippy { paths },
464 "fix" => Subcommand::Fix { paths },
f9f354fc 465 "test" | "t" => Subcommand::Test {
94b46f34
XL
466 paths,
467 bless: matches.opt_present("bless"),
468 compare_mode: matches.opt_str("compare-mode"),
dc9dc135 469 pass: matches.opt_str("pass"),
94b46f34
XL
470 test_args: matches.opt_strs("test-args"),
471 rustc_args: matches.opt_strs("rustc-args"),
472 fail_fast: !matches.opt_present("no-fail-fast"),
532ac7d7 473 rustfix_coverage: matches.opt_present("rustfix-coverage"),
94b46f34
XL
474 doc_tests: if matches.opt_present("doc") {
475 DocTests::Only
476 } else if matches.opt_present("no-doc") {
477 DocTests::No
478 } else {
479 DocTests::Yes
480 },
481 },
dfeec247 482 "bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
f9f354fc 483 "doc" => Subcommand::Doc { paths, open: matches.opt_present("open") },
c30ab7b3 484 "clean" => {
a1dfa0c6 485 if !paths.is_empty() {
ea8adc8c 486 println!("\nclean does not take a path argument\n");
cc61c64b 487 usage(1, &opts, &subcommand_help, &extra_help);
c30ab7b3 488 }
ea8adc8c 489
dfeec247 490 Subcommand::Clean { all: matches.opt_present("all") }
c30ab7b3 491 }
dfeec247 492 "fmt" => Subcommand::Format { check: matches.opt_present("check") },
94b46f34
XL
493 "dist" => Subcommand::Dist { paths },
494 "install" => Subcommand::Install { paths },
f9f354fc 495 "run" | "r" => {
ba9703b0
XL
496 if paths.is_empty() {
497 println!("\nrun requires at least a path!\n");
498 usage(1, &opts, &subcommand_help, &extra_help);
499 }
500 Subcommand::Run { paths }
501 }
cc61c64b
XL
502 _ => {
503 usage(1, &opts, &subcommand_help, &extra_help);
c30ab7b3
SL
504 }
505 };
506
f9f354fc
XL
507 if let Subcommand::Check { .. } = &cmd {
508 if matches.opt_str("stage").is_some() {
509 println!("{}", "--stage not supported for x.py check, always treated as stage 0");
510 process::exit(1);
511 }
512 if matches.opt_str("keep-stage").is_some() {
513 println!(
514 "{}",
515 "--keep-stage not supported for x.py check, only one stage available"
516 );
517 process::exit(1);
518 }
519 }
520
7453a54e 521 Flags {
cc61c64b 522 verbose: matches.opt_count("verbose"),
60c5eb7d 523 stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")),
83c7162d 524 dry_run: matches.opt_present("dry-run"),
cc61c64b 525 on_fail: matches.opt_str("on-fail"),
0531ce1d 526 rustc_error_format: matches.opt_str("error-format"),
ba9703b0 527 json_output: matches.opt_present("json-output"),
dfeec247
XL
528 keep_stage: matches
529 .opt_strs("keep-stage")
530 .into_iter()
531 .map(|j| j.parse().expect("`keep-stage` should be a number"))
8faf50e0 532 .collect(),
a1dfa0c6 533 host: split(&matches.opt_strs("host"))
94b46f34
XL
534 .into_iter()
535 .map(|x| INTERNER.intern_string(x))
536 .collect::<Vec<_>>(),
a1dfa0c6 537 target: split(&matches.opt_strs("target"))
94b46f34
XL
538 .into_iter()
539 .map(|x| INTERNER.intern_string(x))
540 .collect::<Vec<_>>(),
7453a54e 541 config: cfg_file,
60c5eb7d 542 jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")),
3b2f2976 543 cmd,
cc61c64b 544 incremental: matches.opt_present("incremental"),
a1dfa0c6 545 exclude: split(&matches.opt_strs("exclude"))
94b46f34
XL
546 .into_iter()
547 .map(|p| p.into())
548 .collect::<Vec<_>>(),
416331ca 549 deny_warnings: parse_deny_warnings(&matches),
dfeec247
XL
550 llvm_skip_rebuild: matches.opt_str("llvm-skip-rebuild").map(|s| s.to_lowercase()).map(
551 |s| s.parse::<bool>().expect("`llvm-skip-rebuild` should be either true or false"),
552 ),
7453a54e
SL
553 }
554 }
555}
556
c30ab7b3
SL
557impl Subcommand {
558 pub fn test_args(&self) -> Vec<&str> {
559 match *self {
94b46f34 560 Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
dfeec247 561 test_args.iter().flat_map(|s| s.split_whitespace()).collect()
c30ab7b3
SL
562 }
563 _ => Vec::new(),
564 }
7453a54e 565 }
7cac9316 566
2c00a5a8
XL
567 pub fn rustc_args(&self) -> Vec<&str> {
568 match *self {
dfeec247
XL
569 Subcommand::Test { ref rustc_args, .. } => {
570 rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
571 }
2c00a5a8
XL
572 _ => Vec::new(),
573 }
574 }
575
041b39d2 576 pub fn fail_fast(&self) -> bool {
7cac9316 577 match *self {
041b39d2 578 Subcommand::Test { fail_fast, .. } => fail_fast,
7cac9316
XL
579 _ => false,
580 }
581 }
0531ce1d 582
83c7162d 583 pub fn doc_tests(&self) -> DocTests {
0531ce1d
XL
584 match *self {
585 Subcommand::Test { doc_tests, .. } => doc_tests,
83c7162d 586 _ => DocTests::Yes,
0531ce1d
XL
587 }
588 }
94b46f34
XL
589
590 pub fn bless(&self) -> bool {
591 match *self {
592 Subcommand::Test { bless, .. } => bless,
593 _ => false,
594 }
595 }
596
532ac7d7
XL
597 pub fn rustfix_coverage(&self) -> bool {
598 match *self {
599 Subcommand::Test { rustfix_coverage, .. } => rustfix_coverage,
600 _ => false,
601 }
602 }
603
94b46f34
XL
604 pub fn compare_mode(&self) -> Option<&str> {
605 match *self {
dfeec247 606 Subcommand::Test { ref compare_mode, .. } => compare_mode.as_ref().map(|s| &s[..]),
94b46f34
XL
607 _ => None,
608 }
609 }
dc9dc135
XL
610
611 pub fn pass(&self) -> Option<&str> {
612 match *self {
dfeec247 613 Subcommand::Test { ref pass, .. } => pass.as_ref().map(|s| &s[..]),
dc9dc135
XL
614 _ => None,
615 }
616 }
f9f354fc
XL
617
618 pub fn open(&self) -> bool {
619 match *self {
620 Subcommand::Doc { open, .. } => open,
621 _ => false,
622 }
623 }
7453a54e 624}
32a655c1 625
a1dfa0c6 626fn split(s: &[String]) -> Vec<String> {
dfeec247 627 s.iter().flat_map(|s| s.split(',')).map(|s| s.to_string()).collect()
32a655c1 628}
416331ca
XL
629
630fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
74b04a01 631 match matches.opt_str("warnings").as_deref() {
416331ca 632 Some("deny") => Some(true),
e1599b0c 633 Some("warn") => Some(false),
416331ca 634 Some(value) => {
dfeec247 635 eprintln!(r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value,);
416331ca 636 process::exit(1);
dfeec247 637 }
416331ca
XL
638 None => None,
639 }
640}