mod console;
mod exit_code;
mod interrupt;
mod lab;
mod log_file;
mod mutate;
mod options;
mod outcome;
mod output;
mod run;
mod source;
mod textedit;
mod visit;
use std::env;
use std::io;
use std::path::PathBuf;
use std::process::exit;
use anyhow::Result;
use argh::FromArgs;
#[allow(unused)]
use path_slash::PathExt;
use crate::interrupt::check_interrupted;
use crate::lab::Scenario;
use crate::mutate::Mutation;
use crate::options::Options;
use crate::outcome::{Outcome, Phase};
use crate::run::CargoResult;
use crate::source::SourceTree;
#[derive(FromArgs, PartialEq, Debug)]
struct Args {
#[argh(switch)]
all_logs: bool,
#[argh(switch, short = 'v')]
caught: bool,
#[argh(switch)]
check: bool,
#[argh(switch)]
diff: bool,
#[argh(option, short = 'd', default = r#"PathBuf::from(".")"#)]
dir: PathBuf,
#[argh(switch)]
json: bool,
#[argh(switch)]
list: bool,
#[argh(switch)]
no_copy_target: bool,
#[argh(switch)]
no_times: bool,
#[argh(switch)]
shuffle: bool,
#[argh(switch)]
no_shuffle: bool,
#[argh(option, short = 't')]
timeout: Option<f64>,
#[argh(switch, short = 'V')]
unviable: bool,
#[argh(positional)]
cargo_test_args: Vec<String>,
}
fn main() -> Result<()> {
if let Some(subcommand) = env::args().nth(1) {
if subcommand != "mutants" {
eprintln!("unrecognized cargo subcommand {:?}", subcommand);
exit(exit_code::USAGE);
}
} else {
eprintln!("usage: cargo mutants <ARGS>\n or: cargo-mutants mutants <ARGS>");
exit(exit_code::USAGE);
}
let args: Args = argh::cargo_from_env();
let source_tree = SourceTree::new(&args.dir)?;
let options = Options::from(&args);
interrupt::install_handler();
if args.list {
let mutations = source_tree.mutations()?;
if args.json {
if args.diff {
eprintln!("--list --diff --json is not (yet) supported");
exit(exit_code::USAGE);
}
serde_json::to_writer_pretty(io::BufWriter::new(io::stdout()), &mutations)?;
} else {
console::list_mutations(&mutations, args.diff);
}
} else {
let lab_outcome = lab::test_unmutated_then_all_mutants(&source_tree, &options)?;
exit(lab_outcome.exit_code());
}
Ok(())
}