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.
This commit is contained in:
David Ziegler 2019-01-23 18:56:09 +01:00
parent 62d24168d6
commit 7b3daeef9c
7 changed files with 106 additions and 81 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
target
*.tar.gz
*.zip
*.vscode

View File

@ -1,6 +1,6 @@
[package]
name = "watchexec"
version = "1.9.2"
version = "1.9.3"
authors = ["Matt Green <mattgreenrocks@gmail.com>"]
description = "Executes commands in response to file modifications"
documentation = "https://github.com/watchexec/watchexec"

View File

@ -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<String> = 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)
}

View File

@ -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;

View File

@ -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::<fn(_)>)
}

View File

@ -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<op::Op>,
pub cookie: Option<u32>,
pub time: SystemTime,
}
impl PathOp {
@ -15,6 +17,7 @@ impl PathOp {
path: path.to_path_buf(),
op: op,
cookie: cookie,
time: SystemTime::now(),
}
}

View File

@ -32,7 +32,7 @@ fn init_logger(debug: bool) {
.init();
}
pub fn run(args: cli::Args) -> Result<()> {
pub fn run<F>(args: cli::Args, cb: Option<F>) -> Result<()> where F: Fn(Vec<PathOp>) {
let child_process: Arc<RwLock<Option<Process>>> = 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(())
}