From 7b3daeef9c9906e3ee74e30fe707c2e2e447c759 Mon Sep 17 00:00:00 2001 From: David Ziegler Date: Wed, 23 Jan 2019 18:56:09 +0100 Subject: [PATCH] Major changes for c bindings integration as third party crate (see project: github/InfinityMod/watchexec_c). Changed version to 1.9.3 for third party crate compatibility detection. --- .gitignore | 1 + Cargo.toml | 2 +- src/cli.rs | 21 ++++--- src/lib.rs | 2 +- src/main.rs | 2 +- src/pathop.rs | 3 + src/run.rs | 156 +++++++++++++++++++++++++++----------------------- 7 files changed, 106 insertions(+), 81 deletions(-) diff --git a/.gitignore b/.gitignore index c2c87bf..a3aff5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ target *.tar.gz *.zip +*.vscode \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index f6198bc..957ccb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "watchexec" -version = "1.9.2" +version = "1.9.3" authors = ["Matt Green "] description = "Executes commands in response to file modifications" documentation = "https://github.com/watchexec/watchexec" diff --git a/src/cli.rs b/src/cli.rs index d1c343b..b690a2b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,7 +1,7 @@ use std::path::MAIN_SEPARATOR; use std::process::Command; -use clap::{App, Arg, Error}; +use clap::{App, Arg, Error, ArgMatches}; #[derive(Debug)] pub struct Args { @@ -32,10 +32,8 @@ pub fn clear_screen() { let _ = Command::new("tput").arg("reset").status(); } -#[allow(unknown_lints)] -#[allow(or_fun_call)] -pub fn get_args() -> Args { - let args = App::new("watchexec") +pub fn init_app<'a, 'b>() -> App<'a, 'b> { + let app = App::new("watchexec") .version(crate_version!()) .about("Execute commands when watched files change") .arg(Arg::with_name("command") @@ -117,9 +115,11 @@ pub fn get_args() -> Args { .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'") .short("n") .long("no-shell")) - .arg(Arg::with_name("once").short("1").hidden(true)) - .get_matches(); + .arg(Arg::with_name("once").short("1").hidden(true)); + app +} +pub fn process_args(args: ArgMatches) -> Args{ let cmd: Vec = values_t!(args.values_of("command"), String).unwrap(); let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]); @@ -203,3 +203,10 @@ pub fn get_args() -> Args { poll_interval: poll_interval, } } + +#[allow(unknown_lints)] +#[allow(or_fun_call)] +pub fn get_args() -> Args { + let args = init_app().get_matches(); + process_args(args) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6cdd807..cf28533 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ pub mod cli; pub mod error; mod gitignore; mod notification_filter; -mod pathop; +pub mod pathop; mod process; pub mod run; mod signal; diff --git a/src/main.rs b/src/main.rs index bb30a23..955bccd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,5 +2,5 @@ extern crate watchexec; use watchexec::{cli, error, run}; fn main() -> error::Result<()> { - run(cli::get_args()) + run(cli::get_args(), None::) } diff --git a/src/pathop.rs b/src/pathop.rs index 76d987a..41747cb 100644 --- a/src/pathop.rs +++ b/src/pathop.rs @@ -1,5 +1,6 @@ use notify::op; use std::path::{Path, PathBuf}; +use std::time::{SystemTime}; /// Info about a path and its corresponding `notify` event #[derive(Debug, Clone, Hash, Eq, PartialEq)] @@ -7,6 +8,7 @@ pub struct PathOp { pub path: PathBuf, pub op: Option, pub cookie: Option, + pub time: SystemTime, } impl PathOp { @@ -15,6 +17,7 @@ impl PathOp { path: path.to_path_buf(), op: op, cookie: cookie, + time: SystemTime::now(), } } diff --git a/src/run.rs b/src/run.rs index 302b08f..d4465e4 100644 --- a/src/run.rs +++ b/src/run.rs @@ -32,7 +32,7 @@ fn init_logger(debug: bool) { .init(); } -pub fn run(args: cli::Args) -> Result<()> { +pub fn run(args: cli::Args, cb: Option) -> Result<()> where F: Fn(Vec) { let child_process: Arc>> = Arc::new(RwLock::new(None)); let weak_child = Arc::downgrade(&child_process); @@ -103,87 +103,101 @@ pub fn run(args: cli::Args) -> Result<()> { *guard = Some(process::spawn(&args.cmd, vec![], args.no_shell)); } - loop { - debug!("Waiting for filesystem activity"); - let paths = wait_fs(&rx, &filter, args.debounce); - if let Some(path) = paths.get(0) { - debug!("Path updated: {:?}", path); + //Decide if callback cb function or direct execution should be used + let has_cb: bool = cb.is_some(); + if has_cb { + let fcb = cb.unwrap(); + loop { + debug!("Waiting for filesystem activity"); + let paths = wait_fs(&rx, &filter, args.debounce); + if let Some(path) = paths.get(0) { + debug!("Path updated: {:?}", path); + } + //Execute callback + fcb(paths); } + }else{ + loop { + debug!("Waiting for filesystem activity"); + let paths = wait_fs(&rx, &filter, args.debounce); + if let Some(path) = paths.get(0) { + debug!("Path updated: {:?}", path); + } - // We have three scenarios here: - // - // 1. Make sure the previous run was ended, then run the command again - // 2. Just send a specified signal to the child, do nothing more - // 3. Send SIGTERM to the child, wait for it to exit, then run the command again - // 4. Send a specified signal to the child, wait for it to exit, then run the command again - // - let scenario = (args.restart, signal.is_some()); + // We have three scenarios here: + // + // 1. Make sure the previous run was ended, then run the command again + // 2. Just send a specified signal to the child, do nothing more + // 3. Send SIGTERM to the child, wait for it to exit, then run the command again + // 4. Send a specified signal to the child, wait for it to exit, then run the command again + // + let scenario = (args.restart, signal.is_some()); - match scenario { - // Custom restart behaviour (--restart was given, and --signal specified): - // Send specified signal to the child, wait for it to exit, then run the command again - (true, true) => { - signal_process(&child_process, signal, true); + match scenario { + // Custom restart behaviour (--restart was given, and --signal specified): + // Send specified signal to the child, wait for it to exit, then run the command again + (true, true) => { + signal_process(&child_process, signal, true); - // Launch child process - if args.clear_screen { - cli::clear_screen(); + // Launch child process + if args.clear_screen { + cli::clear_screen(); + } + + debug!("Launching child process"); + { + let mut guard = child_process.write().unwrap(); + *guard = Some(process::spawn(&args.cmd, paths, args.no_shell)); + } } - debug!("Launching child process"); - { - let mut guard = child_process.write().unwrap(); - *guard = Some(process::spawn(&args.cmd, paths, args.no_shell)); + // Default restart behaviour (--restart was given, but --signal wasn't specified): + // Send SIGTERM to the child, wait for it to exit, then run the command again + (true, false) => { + let sigterm = signal::new(Some("SIGTERM".to_owned())); + signal_process(&child_process, sigterm, true); + + // Launch child process + if args.clear_screen { + cli::clear_screen(); + } + + debug!("Launching child process"); + { + let mut guard = child_process.write().unwrap(); + *guard = Some(process::spawn(&args.cmd, paths, args.no_shell)); + } + } + + // SIGHUP scenario: --signal was given, but --restart was not + // Just send a signal (e.g. SIGHUP) to the child, do nothing more + (false, true) => signal_process(&child_process, signal, false), + + // Default behaviour (neither --signal nor --restart specified): + // Make sure the previous run was ended, then run the command again + (false, false) => { + signal_process(&child_process, None, true); + + // Launch child process + if args.clear_screen { + cli::clear_screen(); + } + + debug!("Launching child process"); + { + let mut guard = child_process.write().unwrap(); + *guard = Some(process::spawn(&args.cmd, paths, args.no_shell)); + } } } - // Default restart behaviour (--restart was given, but --signal wasn't specified): - // Send SIGTERM to the child, wait for it to exit, then run the command again - (true, false) => { - let sigterm = signal::new(Some("SIGTERM".to_owned())); - signal_process(&child_process, sigterm, true); - - // Launch child process - if args.clear_screen { - cli::clear_screen(); - } - - debug!("Launching child process"); - { - let mut guard = child_process.write().unwrap(); - *guard = Some(process::spawn(&args.cmd, paths, args.no_shell)); - } + // Handle once option for integration testing + if args.once { + signal_process(&child_process, signal, false); + break; } - - // SIGHUP scenario: --signal was given, but --restart was not - // Just send a signal (e.g. SIGHUP) to the child, do nothing more - (false, true) => signal_process(&child_process, signal, false), - - // Default behaviour (neither --signal nor --restart specified): - // Make sure the previous run was ended, then run the command again - (false, false) => { - signal_process(&child_process, None, true); - - // Launch child process - if args.clear_screen { - cli::clear_screen(); - } - - debug!("Launching child process"); - { - let mut guard = child_process.write().unwrap(); - *guard = Some(process::spawn(&args.cmd, paths, args.no_shell)); - } - } - } - - // Handle once option for integration testing - if args.once { - signal_process(&child_process, signal, false); - break; - } + } } - Ok(()) }