extern crate docopt;
extern crate env_logger;
#[macro_use]
extern crate lazy_static;
#[cfg(not(windows))]
extern crate libc;
#[macro_use]
extern crate log;
extern crate notify;
extern crate regex;
extern crate rustc_serialize;
extern crate wait_timeout;
use docopt::Docopt;
use self::watcher::DualWatcher;
use std::process::exit;
use std::sync::mpsc::channel;
use std::time::Duration;
mod cargo;
mod config;
mod schedule;
mod watcher;
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
static USAGE: &'static str = r#"
Usage: cargo-watch [watch] [options]
cargo watch [options]
cargo-watch [watch] [<args>...]
cargo watch [<args>...]
Options:
-h, --help Display this message
--clear Clear the screen before each command
--poll Force use of polling for file updates
--version Show version
`cargo watch` can take one or more arguments to pass to cargo. For example,
`cargo watch "test ex_ --release"` will run `cargo test ex_ --release`
If no arguments are provided, then cargo will run `check`.
"#;
#[derive(RustcDecodable, Debug)]
struct Args {
arg_args: Vec<String>,
flag_clear: bool,
flag_poll: bool,
flag_version: bool,
}
fn main() {
env_logger::init().unwrap();
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|e| e.exit());
if args.flag_version {
println!("cargo-watch {}", VERSION);
exit(0);
}
let mut commands = args.arg_args;
if args.flag_clear {
commands.insert(0, "clear".into());
}
let cargo_dir = match cargo::root() {
Some(path) => path,
None => {
error!("Not a Cargo project, aborting.");
exit(64);
},
};
let (tx, rx) = channel();
let d = Duration::from_secs(1);
let mut watcher = if args.flag_poll {
DualWatcher::fallback_only(tx, d)
} else {
DualWatcher::new(tx, d)
};
for subdir in &config::WATCH_DIRS {
let _ = watcher.watch(&cargo_dir.join(subdir));
}
println!("Waiting for changes... Hit Ctrl-C to stop.");
schedule::handle(rx, commands);
}