#133: leave Handler initialization to watch caller

This commit is contained in:
Wayne Warren 2019-10-26 19:50:45 +00:00 committed by Félix Saparelli
parent 31b5cb0ab6
commit 720ff44b71
1 changed files with 35 additions and 31 deletions

View File

@ -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<Self>
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<bool>;
fn on_manual(&self) -> Result<bool>;
/// 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<bool>;
fn on_update(&self, ops: &[PathOp]) -> Result<bool>;
/// 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<H>(args: Args) -> Result<()>
pub fn watch<H>(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<Signal>,
child_process: Arc<RwLock<Option<Process>>>,
}
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<Self> {
impl<'a> ExecHandler<'a> {
pub fn new(args: &'a Args) -> Result<Self> {
let child_process: Arc<RwLock<Option<Process>>> = 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<bool> {
fn on_manual(&self) -> Result<bool> {
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<bool> {
fn on_update(&self, ops: &[PathOp]) -> Result<bool> {
// 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::<ExecHandler>(args)
let handler = ExecHandler::new(&args)?;
watch(&handler)
}
fn wait_fs(rx: &Receiver<Event>, filter: &NotificationFilter, debounce: u64) -> Vec<PathOp> {