1extern crate clap;
2extern crate glob;
3extern crate notify;
4extern crate notify_rust;
5extern crate regex;
6#[macro_use]
7extern crate error_chain;
8
9use clap::{App, Arg, SubCommand};
10
11mod config;
12mod errors;
13mod reactor;
14mod report;
15mod report_builder;
16use config::ConfigBuilder;
17use reactor::Reactor;
18
19pub fn run() {
20 let matches = App::new("cargo")
21 .bin_name("cargo")
22 .help_message("")
23 .version_message("")
24 .subcommand(
25 SubCommand::with_name("testify")
26 .version("0.2.0")
27 .author("Sergey Potapov <blake131313@gmail.com>")
28 .about("Automatically runs tests for Rust project and notifies about the result.\nSource code: https://github.com/greyblake/cargo-testify")
29 .arg(Arg::with_name("includes")
30 .short("i")
31 .long("include")
32 .takes_value(true)
33 .help("Comma separated list of include pattern in addition to the predefined default patterns"))
34 .arg(Arg::with_name("cargo_test_args")
35 .multiple(true)
36 .last(true))
37 )
38 .get_matches();
39
40 let cargo_test_args = if let Some(matches) = matches.subcommand_matches("testify") {
41 matches
42 .values_of("cargo_test_args")
43 .map(|vals| vals.collect::<Vec<_>>())
44 .unwrap_or(vec![])
45 } else {
46 vec![]
47 };
48
49 let include_patterns = matches
50 .subcommand_matches("testify")
51 .and_then(|m| m.value_of("includes"))
52 .map(|vals| vals.split(',').collect::<Vec<_>>())
53 .unwrap_or(vec![]);
54
55 let project_dir = detect_project_dir();
56 let config = ConfigBuilder::new()
57 .project_dir(project_dir)
58 .include_patterns(&include_patterns)
59 .cargo_test_args(cargo_test_args)
60 .build()
61 .unwrap();
62
63 Reactor::new(config).start()
64}
65
66fn detect_project_dir() -> std::path::PathBuf {
71 let current_dir = std::env::current_dir().expect("Failed to get current directory");
72 let mut optional_dir = Some(current_dir.as_path());
73
74 while let Some(dir) = optional_dir {
75 let cargo_toml = dir.join("Cargo.toml");
76 if cargo_toml.is_file() {
77 return dir.to_path_buf();
78 }
79 optional_dir = dir.parent();
80 }
81
82 eprintln!(
83 "Error: could not find `Cargo.toml` in {:?} or any parent directory.",
84 current_dir
85 );
86 std::process::exit(1);
87}