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:
parent
62d24168d6
commit
7b3daeef9c
|
@ -1,3 +1,4 @@
|
||||||
target
|
target
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.zip
|
*.zip
|
||||||
|
*.vscode
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "watchexec"
|
name = "watchexec"
|
||||||
version = "1.9.2"
|
version = "1.9.3"
|
||||||
authors = ["Matt Green <mattgreenrocks@gmail.com>"]
|
authors = ["Matt Green <mattgreenrocks@gmail.com>"]
|
||||||
description = "Executes commands in response to file modifications"
|
description = "Executes commands in response to file modifications"
|
||||||
documentation = "https://github.com/watchexec/watchexec"
|
documentation = "https://github.com/watchexec/watchexec"
|
||||||
|
|
21
src/cli.rs
21
src/cli.rs
|
@ -1,7 +1,7 @@
|
||||||
use std::path::MAIN_SEPARATOR;
|
use std::path::MAIN_SEPARATOR;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use clap::{App, Arg, Error};
|
use clap::{App, Arg, Error, ArgMatches};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
|
@ -32,10 +32,8 @@ pub fn clear_screen() {
|
||||||
let _ = Command::new("tput").arg("reset").status();
|
let _ = Command::new("tput").arg("reset").status();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unknown_lints)]
|
pub fn init_app<'a, 'b>() -> App<'a, 'b> {
|
||||||
#[allow(or_fun_call)]
|
let app = App::new("watchexec")
|
||||||
pub fn get_args() -> Args {
|
|
||||||
let args = App::new("watchexec")
|
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.about("Execute commands when watched files change")
|
.about("Execute commands when watched files change")
|
||||||
.arg(Arg::with_name("command")
|
.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'")
|
.help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
|
||||||
.short("n")
|
.short("n")
|
||||||
.long("no-shell"))
|
.long("no-shell"))
|
||||||
.arg(Arg::with_name("once").short("1").hidden(true))
|
.arg(Arg::with_name("once").short("1").hidden(true));
|
||||||
.get_matches();
|
app
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_args(args: ArgMatches) -> Args{
|
||||||
let cmd: Vec<String> = values_t!(args.values_of("command"), String).unwrap();
|
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(".")]);
|
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,
|
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)
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ pub mod cli;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod gitignore;
|
mod gitignore;
|
||||||
mod notification_filter;
|
mod notification_filter;
|
||||||
mod pathop;
|
pub mod pathop;
|
||||||
mod process;
|
mod process;
|
||||||
pub mod run;
|
pub mod run;
|
||||||
mod signal;
|
mod signal;
|
||||||
|
|
|
@ -2,5 +2,5 @@ extern crate watchexec;
|
||||||
use watchexec::{cli, error, run};
|
use watchexec::{cli, error, run};
|
||||||
|
|
||||||
fn main() -> error::Result<()> {
|
fn main() -> error::Result<()> {
|
||||||
run(cli::get_args())
|
run(cli::get_args(), None::<fn(_)>)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use notify::op;
|
use notify::op;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::time::{SystemTime};
|
||||||
|
|
||||||
/// Info about a path and its corresponding `notify` event
|
/// Info about a path and its corresponding `notify` event
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||||
|
@ -7,6 +8,7 @@ pub struct PathOp {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub op: Option<op::Op>,
|
pub op: Option<op::Op>,
|
||||||
pub cookie: Option<u32>,
|
pub cookie: Option<u32>,
|
||||||
|
pub time: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathOp {
|
impl PathOp {
|
||||||
|
@ -15,6 +17,7 @@ impl PathOp {
|
||||||
path: path.to_path_buf(),
|
path: path.to_path_buf(),
|
||||||
op: op,
|
op: op,
|
||||||
cookie: cookie,
|
cookie: cookie,
|
||||||
|
time: SystemTime::now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
156
src/run.rs
156
src/run.rs
|
@ -32,7 +32,7 @@ fn init_logger(debug: bool) {
|
||||||
.init();
|
.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 child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
|
||||||
let weak_child = Arc::downgrade(&child_process);
|
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));
|
*guard = Some(process::spawn(&args.cmd, vec![], args.no_shell));
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
//Decide if callback cb function or direct execution should be used
|
||||||
debug!("Waiting for filesystem activity");
|
let has_cb: bool = cb.is_some();
|
||||||
let paths = wait_fs(&rx, &filter, args.debounce);
|
if has_cb {
|
||||||
if let Some(path) = paths.get(0) {
|
let fcb = cb.unwrap();
|
||||||
debug!("Path updated: {:?}", path);
|
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:
|
// We have three scenarios here:
|
||||||
//
|
//
|
||||||
// 1. Make sure the previous run was ended, then run the command again
|
// 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
|
// 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
|
// 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
|
// 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());
|
let scenario = (args.restart, signal.is_some());
|
||||||
|
|
||||||
match scenario {
|
match scenario {
|
||||||
// Custom restart behaviour (--restart was given, and --signal specified):
|
// 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
|
// Send specified signal to the child, wait for it to exit, then run the command again
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
signal_process(&child_process, signal, true);
|
signal_process(&child_process, signal, true);
|
||||||
|
|
||||||
// Launch child process
|
// Launch child process
|
||||||
if args.clear_screen {
|
if args.clear_screen {
|
||||||
cli::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");
|
// 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
|
||||||
let mut guard = child_process.write().unwrap();
|
(true, false) => {
|
||||||
*guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
|
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):
|
// Handle once option for integration testing
|
||||||
// Send SIGTERM to the child, wait for it to exit, then run the command again
|
if args.once {
|
||||||
(true, false) => {
|
signal_process(&child_process, signal, false);
|
||||||
let sigterm = signal::new(Some("SIGTERM".to_owned()));
|
break;
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle once option for integration testing
|
|
||||||
if args.once {
|
|
||||||
signal_process(&child_process, signal, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue