Support watching multiple paths
This commit is contained in:
parent
cd083ef650
commit
e16a6b3a24
|
@ -1,6 +1,6 @@
|
|||
[root]
|
||||
name = "watchexec"
|
||||
version = "1.6.2"
|
||||
version = "1.7.0"
|
||||
dependencies = [
|
||||
"clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
11
src/cli.rs
11
src/cli.rs
|
@ -6,6 +6,7 @@ use clap::{App, Arg};
|
|||
#[derive(Debug)]
|
||||
pub struct Args {
|
||||
pub cmd: String,
|
||||
pub paths: Vec<String>,
|
||||
pub filters: Vec<String>,
|
||||
pub ignores: Vec<String>,
|
||||
pub clear_screen: bool,
|
||||
|
@ -44,6 +45,13 @@ pub fn get_args() -> Args {
|
|||
.short("e")
|
||||
.long("exts")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("path")
|
||||
.help("Watch a specific directory")
|
||||
.short("w")
|
||||
.long("watch")
|
||||
.number_of_values(1)
|
||||
.multiple(true)
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("clear")
|
||||
.help("Clear screen before executing command")
|
||||
.short("c")
|
||||
|
@ -93,6 +101,8 @@ pub fn get_args() -> Args {
|
|||
.get_matches();
|
||||
|
||||
let cmd = values_t!(args.values_of("command"), String).unwrap().join(" ");
|
||||
let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]);
|
||||
|
||||
let mut filters = values_t!(args.values_of("filter"), String).unwrap_or(vec![]);
|
||||
|
||||
if let Some(extensions) = args.values_of("extensions") {
|
||||
|
@ -121,6 +131,7 @@ pub fn get_args() -> Args {
|
|||
|
||||
Args {
|
||||
cmd: cmd,
|
||||
paths: paths,
|
||||
filters: filters,
|
||||
ignores: ignores,
|
||||
clear_screen: args.is_present("clear"),
|
||||
|
|
|
@ -41,7 +41,7 @@ enum MatchResult {
|
|||
None,
|
||||
}
|
||||
|
||||
pub fn load(paths: Vec<&Path>) -> Gitignore {
|
||||
pub fn load(paths: &Vec<PathBuf>) -> Gitignore {
|
||||
let mut files = vec![];
|
||||
let mut checked_dirs = HashSet::new();
|
||||
|
||||
|
|
26
src/main.rs
26
src/main.rs
|
@ -27,8 +27,7 @@ mod signal;
|
|||
mod watcher;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::time::Duration;
|
||||
|
@ -79,34 +78,31 @@ fn main() {
|
|||
|
||||
init_logger(args.debug);
|
||||
|
||||
let cwd = env::current_dir()
|
||||
.expect("unable to get cwd")
|
||||
.canonicalize()
|
||||
.expect("unable to canonicalize cwd");
|
||||
let paths: Vec<PathBuf> = args.paths
|
||||
.iter()
|
||||
.map(|p| Path::new(&p)
|
||||
.canonicalize()
|
||||
.expect(&format!("unable to canonicalize \"{}\"", &p))
|
||||
.to_owned())
|
||||
.collect();
|
||||
|
||||
let gitignore = if !args.no_vcs_ignore {
|
||||
gitignore::load(vec![&cwd])
|
||||
gitignore::load(&paths)
|
||||
} else {
|
||||
gitignore::load(vec![])
|
||||
gitignore::load(&vec![])
|
||||
};
|
||||
|
||||
let filter = NotificationFilter::new(args.filters, args.ignores, gitignore)
|
||||
.expect("unable to create notification filter");
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let mut watcher = Watcher::new(tx, args.poll, args.poll_interval)
|
||||
let watcher = Watcher::new(tx, &paths, args.poll, args.poll_interval)
|
||||
.expect("unable to create watcher");
|
||||
|
||||
if watcher.is_polling() {
|
||||
warn!("Polling for changes every {} ms", args.poll_interval);
|
||||
}
|
||||
|
||||
let result = watcher.watch(cwd);
|
||||
if let Err(e) = result {
|
||||
error!("Unable to watch directory/subdirectory: {}", e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start child process initially, if necessary
|
||||
if args.run_initially && !args.once {
|
||||
if args.clear_screen {
|
||||
|
|
|
@ -94,7 +94,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_allows_everything_by_default() {
|
||||
let filter = NotificationFilter::new(vec![], vec![], gitignore::load(vec![])).unwrap();
|
||||
let filter = NotificationFilter::new(vec![], vec![], gitignore::load(&vec![])).unwrap();
|
||||
|
||||
assert!(!filter.is_excluded(&Path::new("foo")));
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_multiple_filters() {
|
||||
let filters = vec![String::from("*.rs"), String::from("*.toml")];
|
||||
let filter = NotificationFilter::new(filters, vec![], gitignore::load(vec![])).unwrap();
|
||||
let filter = NotificationFilter::new(filters, vec![], gitignore::load(&vec![])).unwrap();
|
||||
|
||||
assert!(!filter.is_excluded(&Path::new("hello.rs")));
|
||||
assert!(!filter.is_excluded(&Path::new("Cargo.toml")));
|
||||
|
@ -112,7 +112,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_multiple_ignores() {
|
||||
let ignores = vec![String::from("*.rs"), String::from("*.toml")];
|
||||
let filter = NotificationFilter::new(vec![], ignores, gitignore::load(vec![])).unwrap();
|
||||
let filter = NotificationFilter::new(vec![], ignores, gitignore::load(&vec![])).unwrap();
|
||||
|
||||
assert!(filter.is_excluded(&Path::new("hello.rs")));
|
||||
assert!(filter.is_excluded(&Path::new("Cargo.toml")));
|
||||
|
@ -122,7 +122,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_ignores_take_precedence() {
|
||||
let ignores = vec![String::from("*.rs"), String::from("*.toml")];
|
||||
let filter = NotificationFilter::new(ignores.clone(), ignores, gitignore::load(vec![]))
|
||||
let filter = NotificationFilter::new(ignores.clone(), ignores, gitignore::load(&vec![]))
|
||||
.unwrap();
|
||||
|
||||
assert!(filter.is_excluded(&Path::new("hello.rs")));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
use notify::{PollWatcher, RecommendedWatcher, RecursiveMode, raw_watcher};
|
||||
|
@ -22,14 +22,28 @@ enum WatcherImpl {
|
|||
}
|
||||
|
||||
impl Watcher {
|
||||
pub fn new(tx: Sender<Event>, poll: bool, interval_ms: u32) -> Result<Watcher, Error> {
|
||||
pub fn new(tx: Sender<Event>, paths: &Vec<PathBuf>, poll: bool, interval_ms: u32) -> Result<Watcher, Error> {
|
||||
use notify::Watcher;
|
||||
|
||||
let imp = if poll {
|
||||
WatcherImpl::Poll(try!(PollWatcher::with_delay_ms(tx, interval_ms)))
|
||||
let mut watcher = try!(PollWatcher::with_delay_ms(tx, interval_ms));
|
||||
for ref path in paths {
|
||||
try!(watcher.watch(path, RecursiveMode::Recursive));
|
||||
debug!("Watching {:?}", path);
|
||||
}
|
||||
|
||||
WatcherImpl::Poll(watcher)
|
||||
} else {
|
||||
WatcherImpl::Recommended(try!(raw_watcher(tx)))
|
||||
let mut watcher = try!(raw_watcher(tx));
|
||||
for ref path in paths {
|
||||
try!(watcher.watch(path, RecursiveMode::Recursive));
|
||||
debug!("Watching {:?}", path);
|
||||
}
|
||||
|
||||
WatcherImpl::Recommended(watcher)
|
||||
};
|
||||
|
||||
Ok(Watcher { watcher_impl: imp })
|
||||
Ok(self::Watcher { watcher_impl: imp })
|
||||
}
|
||||
|
||||
pub fn is_polling(&self) -> bool {
|
||||
|
@ -39,13 +53,4 @@ impl Watcher {
|
|||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn watch<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error> {
|
||||
use notify::Watcher;
|
||||
|
||||
match self.watcher_impl {
|
||||
WatcherImpl::Recommended(ref mut w) => w.watch(path, RecursiveMode::Recursive),
|
||||
WatcherImpl::Poll(ref mut w) => w.watch(path, RecursiveMode::Recursive),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue