diff --git a/src/error.rs b/src/error.rs index 0f3f743..a51a534 100644 --- a/src/error.rs +++ b/src/error.rs @@ -23,9 +23,7 @@ pub struct CommandError { impl CommandError { pub fn new(msg: String) -> CommandError { - CommandError{ - msg: msg - } + CommandError { msg: msg } } } diff --git a/src/events.rs b/src/events.rs index 128f540..0120a8a 100644 --- a/src/events.rs +++ b/src/events.rs @@ -18,7 +18,7 @@ pub enum WatchEventType { Touched, Changed, Error, - Ignore + Ignore, } impl From for WatchEventType { @@ -32,7 +32,7 @@ impl From for WatchEventType { DebouncedEvent::NoticeRemove(_) => WatchEventType::Ignore, DebouncedEvent::NoticeWrite(_) => WatchEventType::Ignore, DebouncedEvent::Rescan => WatchEventType::Ignore, - DebouncedEvent::Error(_, _) => WatchEventType::Ignore + DebouncedEvent::Error(_, _) => WatchEventType::Ignore, } } } diff --git a/src/exec.rs b/src/exec.rs index 442f7f1..5956127 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -14,7 +14,7 @@ use std::thread; use std::time::Duration; -use subprocess::{Exec,PopenError,ExitStatus}; +use subprocess::{Exec, PopenError, ExitStatus}; use traits::Process; use error::CommandError; @@ -39,7 +39,11 @@ pub struct ExecProcess<'a> { impl<'a> ExecProcess<'a> { pub fn new(test_cmd: &'a str, cmd: &'a str, poll: Duration) -> ExecProcess<'a> { - ExecProcess{test_cmd: test_cmd, cmd: cmd, poll: poll} + ExecProcess { + test_cmd: test_cmd, + cmd: cmd, + poll: poll, + } } } diff --git a/src/file.rs b/src/file.rs index a01a761..282be67 100644 --- a/src/file.rs +++ b/src/file.rs @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. use std::thread; -use std::sync::{Arc,Mutex}; +use std::sync::{Arc, Mutex}; use std::time::Duration; use std::path::Path; use std::sync::mpsc::channel; -use notify::{Watcher,RecursiveMode,watcher}; +use notify::{Watcher, RecursiveMode, watcher}; use traits::Process; use error::CommandError; @@ -32,8 +32,17 @@ pub struct FileProcess<'a> { } impl<'a> FileProcess<'a> { - pub fn new(cmd: &'a str, file: &'a str, method: WatchEventType, poll: Duration) -> FileProcess<'a> { - FileProcess{ cmd: cmd, file: file, method: method, poll: poll} + pub fn new(cmd: &'a str, + file: &'a str, + method: WatchEventType, + poll: Duration) + -> FileProcess<'a> { + FileProcess { + cmd: cmd, + file: file, + method: method, + poll: poll, + } } } @@ -57,7 +66,10 @@ fn spawn_runner_thread(lock: Arc>, cmd: String, poll: Duration) { }); } -fn wait_for_fs_events(lock: Arc>, method: WatchEventType, file: &str) -> Result<(), CommandError> { +fn wait_for_fs_events(lock: Arc>, + method: WatchEventType, + file: &str) + -> Result<(), CommandError> { // Notify requires a channel for communication. let (tx, rx) = channel(); let mut watcher = try!(watcher(tx, Duration::from_secs(1))); @@ -66,26 +78,22 @@ fn wait_for_fs_events(lock: Arc>, method: WatchEventType, file: &str println!("Watching {:?}", file); loop { let evt: WatchEventType = match rx.recv() { - Ok(event) => { - WatchEventType::from(event) - }, - Err(_) => { - WatchEventType::Error - } + Ok(event) => WatchEventType::from(event), + Err(_) => WatchEventType::Error, }; match evt { WatchEventType::Ignore => { // We ignore this one. - }, + } WatchEventType::Error => { // We log this one. - }, + } WatchEventType::Touched => { if method == WatchEventType::Touched { let mut signal = lock.lock().unwrap(); *signal = true; } - }, + } WatchEventType::Changed => { let mut signal = lock.lock().unwrap(); *signal = true; @@ -96,15 +104,15 @@ fn wait_for_fs_events(lock: Arc>, method: WatchEventType, file: &str impl<'a> Process for FileProcess<'a> { fn run(&self) -> Result<(), CommandError> { - // NOTE(jwall): this is necessary because notify::fsEventWatcher panics - // if the path doesn't exist. :-( - if !Path::new(self.file).exists() { - return Err(CommandError::new(format!("No such path! {0}", self.file).to_string())) - } - // TODO(jeremy): Is this sufficent or do we want to ignore - // any events that come in while the command is running? - let lock = Arc::new(Mutex::new(false)); - spawn_runner_thread(lock.clone(), self.cmd.to_string(), self.poll); - wait_for_fs_events(lock, self.method.clone(), self.file) + // NOTE(jwall): this is necessary because notify::fsEventWatcher panics + // if the path doesn't exist. :-( + if !Path::new(self.file).exists() { + return Err(CommandError::new(format!("No such path! {0}", self.file).to_string())); + } + // TODO(jeremy): Is this sufficent or do we want to ignore + // any events that come in while the command is running? + let lock = Arc::new(Mutex::new(false)); + spawn_runner_thread(lock.clone(), self.cmd.to_string(), self.poll); + wait_for_fs_events(lock, self.method.clone(), self.file) } } diff --git a/src/main.rs b/src/main.rs index 7d1c473..5061085 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -//! runwhen - A utility that runs commands on user defined triggers. +// runwhen - A utility that runs commands on user defined triggers. #[macro_use] extern crate clap; extern crate humantime; @@ -44,21 +44,29 @@ fn do_flags<'a>() -> clap::ArgMatches<'a> { (@subcommand watch => (about: "Trigger that fires when a file or directory changes.") // TODO(jeremy): We need to support filters - (@arg file: -f --file +takes_value "File/Directory to watch. (default current working directory)") - (@arg filetouch: --touch "Watches for attribute modifications as well as content changes.") - (@arg wait: --poll +takes_value "How frequently to poll for events (default 5s)") + (@arg file: -f --file +takes_value + "File/Directory to watch. (default current working directory)") + (@arg filetouch: --touch + "Watches for attribute modifications as well as content changes.") + (@arg wait: --poll +takes_value + "How frequently to poll for events (default 5s)") ) (@subcommand timer => (about: "Trigger that fires on a timer.") - (@arg duration: -t --duration +required +takes_value "Defines timer frequency.") - (@arg repeat: -n --repeat +takes_value "Defines an optional max number times to run on repeat.") + (@arg duration: -t --duration +required +takes_value + "Defines timer frequency.") + (@arg repeat: -n --repeat +takes_value + "Defines an optional max number times to run on repeat.") ) (@subcommand success => (about: "Trigger that fires if a command runs successful.") - (@arg ifcmd: --if +required +takes_value "The command to test for successful exit from") - (@arg wait: --poll +takes_value "How frequently to test command (default 5s)") + (@arg ifcmd: --if +required +takes_value + "The command to test for successful exit from") + (@arg wait: --poll +takes_value + "How frequently to test command (default 5s)") ) - ).get_matches() + ) + .get_matches() } fn main() { @@ -78,9 +86,10 @@ fn main() { process = Some(Box::new(FileProcess::new(cmd, file, method, dur))); } else if let Some(matches) = app.subcommand_matches("timer") { // Unwrap because this flag is required. - let dur = humantime::parse_duration(matches.value_of("duration").expect("duration flag is required")); + let dur = humantime::parse_duration(matches.value_of("duration") + .expect("duration flag is required")); match dur { - Ok(duration) =>{ + Ok(duration) => { let max_repeat = if let Some(val) = matches.value_of("repeat") { match u32::from_str(val) { Ok(n) => Some(n), @@ -94,7 +103,7 @@ fn main() { None }; process = Some(Box::new(TimerProcess::new(cmd, duration, max_repeat))); - }, + } Err(msg) => { println!("Malformed duration {:?}", msg); process::exit(1); @@ -103,8 +112,7 @@ fn main() { } else if let Some(matches) = app.subcommand_matches("success") { // unwrap because this is required. let ifcmd = matches.value_of("ifcmd").expect("ifcmd flag is required"); - let dur = humantime::parse_duration( - matches.value_of("poll").unwrap_or("5s")); + let dur = humantime::parse_duration(matches.value_of("poll").unwrap_or("5s")); process = match dur { Ok(duration) => Some(Box::new(ExecProcess::new(ifcmd, cmd, duration))), Err(msg) => { @@ -114,16 +122,18 @@ fn main() { } } match process { - Some(process) => match process.run() { - Ok(_) => return, - Err(err) => { - println!("{0}", err); - process::exit(1) + Some(process) => { + match process.run() { + Ok(_) => return, + Err(err) => { + println!("{0}", err); + process::exit(1) + } } - }, + } None => { println!("You must specify a subcommand."); process::exit(1) - }, + } } } diff --git a/src/timer.rs b/src/timer.rs index c1c4599..462da3f 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -21,12 +21,16 @@ use exec::run_cmd; pub struct TimerProcess<'a> { cmd: &'a str, poll_duration: Duration, - max_repeat: Option + max_repeat: Option, } impl<'a> TimerProcess<'a> { pub fn new(cmd: &'a str, poll_duration: Duration, max_repeat: Option) -> TimerProcess<'a> { - TimerProcess{cmd: cmd, poll_duration: poll_duration, max_repeat: max_repeat} + TimerProcess { + cmd: cmd, + poll_duration: poll_duration, + max_repeat: max_repeat, + } } } @@ -41,7 +45,9 @@ impl<'a> Process for TimerProcess<'a> { println!("{:?}", err) } thread::sleep(self.poll_duration); - if self.max_repeat.is_some() { counter += 1 } + if self.max_repeat.is_some() { + counter += 1 + } } } }