From 720ff44b71254a43d110813a183ca0a4ec9343b8 Mon Sep 17 00:00:00 2001 From: Wayne Warren Date: Sat, 26 Oct 2019 19:50:45 +0000 Subject: [PATCH] #133: leave Handler initialization to watch caller --- src/run.rs | 66 +++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/src/run.rs b/src/run.rs index 3df1c96..c1bdb12 100644 --- a/src/run.rs +++ b/src/run.rs @@ -33,11 +33,6 @@ fn init_logger(debug: bool) { } pub trait Handler { - /// Initialises the `Handler` with a copy of the arguments. - fn new(args: Args) -> Result - where - Self: Sized; - /// Called through a manual request, such as an initial run. /// /// # Returns @@ -47,7 +42,7 @@ pub trait Handler { /// - `Err`: an error has occurred while processing, quit. /// - `Ok(true)`: everything is fine and the loop can continue. /// - `Ok(false)`: everything is fine but we should gracefully stop. - fn on_manual(&mut self) -> Result; + fn on_manual(&self) -> Result; /// Called through a file-update request. /// @@ -62,22 +57,26 @@ pub trait Handler { /// - `Err`: an error has occurred while processing, quit. /// - `Ok(true)`: everything is fine and the loop can continue. /// - `Ok(false)`: everything is fine but we should gracefully stop. - fn on_update(&mut self, ops: &[PathOp]) -> Result; + fn on_update(&self, ops: &[PathOp]) -> Result; + + /// Handler implementations must return a customized watchexec Args reference for use in the + /// calling watcher. + fn args(&self) -> &Args; } /// Starts watching, and calls a handler when something happens. /// /// Given an argument structure and a `Handler` type, starts the watcher /// loop (blocking until done). -pub fn watch(args: Args) -> Result<()> +pub fn watch(handler: &H) -> Result<()> where H: Handler, { + let args = handler.args(); init_logger(args.debug); - let mut handler = H::new(args.clone())?; let mut paths = vec![]; - for path in args.paths { + for path in &args.paths { paths.push( canonicalize(&path) .map_err(|e| Error::Canonicalization(path.to_string_lossy().into_owned(), e))?, @@ -143,28 +142,14 @@ where Ok(()) } -pub struct ExecHandler { - args: Args, +pub struct ExecHandler<'a> { + args: &'a Args, signal: Option, child_process: Arc>>, } -impl ExecHandler { - fn spawn(&mut self, ops: &[PathOp]) -> Result<()> { - if self.args.clear_screen { - clear_screen(); - } - - debug!("Launching child process"); - let mut guard = self.child_process.write()?; - *guard = Some(process::spawn(&self.args.cmd, ops, self.args.no_shell)?); - - Ok(()) - } -} - -impl Handler for ExecHandler { - fn new(args: Args) -> Result { +impl<'a> ExecHandler<'a> { + pub fn new(args: &'a Args) -> Result { let child_process: Arc>> = Arc::new(RwLock::new(None)); let weak_child = Arc::downgrade(&child_process); @@ -190,8 +175,26 @@ impl Handler for ExecHandler { }) } + fn spawn(&self, ops: &[PathOp]) -> Result<()> { + if self.args.clear_screen { + clear_screen(); + } + + debug!("Launching child process"); + let mut guard = self.child_process.write()?; + *guard = Some(process::spawn(&self.args.cmd, ops, self.args.no_shell)?); + + Ok(()) + } +} + +impl<'a> Handler for ExecHandler<'a> { + fn args(&self) -> &Args { + &self.args + } + // Only returns Err() on lock poisoning. - fn on_manual(&mut self) -> Result { + fn on_manual(&self) -> Result { if self.args.once { return Ok(true); } @@ -201,7 +204,7 @@ impl Handler for ExecHandler { } // Only returns Err() on lock poisoning. - fn on_update(&mut self, ops: &[PathOp]) -> Result { + fn on_update(&self, ops: &[PathOp]) -> Result { // We have four scenarios here: // // 1. Send a specified signal to the child, wait for it to exit, then run the command again @@ -250,7 +253,8 @@ impl Handler for ExecHandler { } pub fn run(args: Args) -> Result<()> { - watch::(args) + let handler = ExecHandler::new(&args)?; + watch(&handler) } fn wait_fs(rx: &Receiver, filter: &NotificationFilter, debounce: u64) -> Vec {