[run] Always canonicalize input paths (#113)

A client may pass non-canonicalized paths into `watch`, and these are therefore not matched against the filters correctly. Thus, some events could call a Handler's `on_update` method even when an ignored file was changed.

See repro: https://github.com/SpiralP/rust-cargo-watch-test

This bug was introduced in aae5a216b0.
This commit is contained in:
SpiralP 2019-03-03 14:40:35 -08:00 committed by Félix Saparelli
parent 867ef7bc3c
commit dbc52e012e
2 changed files with 18 additions and 10 deletions

View File

@ -2,7 +2,6 @@ use clap::{App, Arg, Error};
use error;
use std::{
ffi::OsString,
fs::canonicalize,
path::{PathBuf, MAIN_SEPARATOR},
process::Command,
};
@ -146,11 +145,11 @@ where
};
let cmd: Vec<String> = values_t!(args.values_of("command"), String)?;
let str_paths = values_t!(args.values_of("path"), String).unwrap_or(vec![".".into()]);
let mut paths = vec![];
for path in str_paths {
paths.push(canonicalize(&path).map_err(|e| error::Error::Canonicalization(path, e))?);
}
let paths = values_t!(args.values_of("path"), String)
.unwrap_or(vec![".".into()])
.iter()
.map(|string_path| string_path.into())
.collect();
// Treat --kill as --signal SIGKILL (for compatibility with older syntax)
let signal = if args.is_present("kill") {

View File

@ -1,6 +1,6 @@
use cli::{clear_screen, Args};
use env_logger;
use error::Result;
use error::{Error, Result};
use gitignore;
use log;
use notification_filter::NotificationFilter;
@ -11,6 +11,7 @@ use process::{self, Process};
use signal::{self, Signal};
use std::{
collections::HashMap,
fs::canonicalize,
io::Write,
sync::{
mpsc::{channel, Receiver},
@ -78,14 +79,22 @@ where
init_logger(args.debug);
let mut handler = H::new(args.clone())?;
let gitignore = gitignore::load(if args.no_vcs_ignore { &[] } else { &args.paths });
let mut paths = vec![];
for path in args.paths {
paths.push(
canonicalize(&path)
.map_err(|e| Error::Canonicalization(path.to_string_lossy().into_owned(), e))?,
);
}
let gitignore = gitignore::load(if args.no_vcs_ignore { &[] } else { &paths });
let filter = NotificationFilter::new(&args.filters, &args.ignores, gitignore)?;
let (tx, rx) = channel();
let poll = args.poll.clone();
#[cfg(target_os = "linux")]
let poll_interval = args.poll_interval.clone();
let watcher = Watcher::new(tx.clone(), &args.paths, args.poll, args.poll_interval).or_else(|err| {
let watcher = Watcher::new(tx.clone(), &paths, args.poll, args.poll_interval).or_else(|err| {
if poll {
return Err(err);
}
@ -102,7 +111,7 @@ where
}
if fallback {
return Watcher::new(tx, &args.paths, true, poll_interval);
return Watcher::new(tx, &paths, true, poll_interval);
}
}