From b10601d96abcd72025ff04dddf28d51a41f02511 Mon Sep 17 00:00:00 2001 From: Tom Doerr Date: Thu, 2 Apr 2020 19:40:08 +0200 Subject: [PATCH 1/2] Add kill flag --- whenchanged/whenchanged.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/whenchanged/whenchanged.py b/whenchanged/whenchanged.py index 1de6aa0..3611361 100755 --- a/whenchanged/whenchanged.py +++ b/whenchanged/whenchanged.py @@ -13,6 +13,7 @@ -1 Don't re-run command if files changed while command was running -s Run command immediately at start -q Run command quietly +-k Kill the currently running command and kick off a fresh one if a file changes Environment variables: - WHEN_CHANGED_EVENT: reflects the current event type that occurs. @@ -29,6 +30,8 @@ import sys import os import re +import multiprocessing +import signal import time from datetime import datetime from watchdog.observers import Observer @@ -56,7 +59,8 @@ class WhenChanged(FileSystemEventHandler): ])) def __init__(self, files, command, recursive=False, run_once=False, - run_at_start=False, verbose_mode=0, quiet_mode=False): + run_at_start=False, verbose_mode=0, quiet_mode=False, + kill_running=False): self.files = files paths = {} for f in files: @@ -69,8 +73,10 @@ def __init__(self, files, command, recursive=False, run_once=False, self.last_run = 0 self.verbose_mode = verbose_mode self.quiet_mode = quiet_mode + self.kill_running = kill_running self.process_env = os.environ.copy() + self.command_process = None self.observer = Observer(timeout=0.1) for p in self.paths: @@ -102,7 +108,14 @@ def run_command(self, thefile): print('==> ' + print_message + ' <==') self.set_envvar('file', thefile) stdout = open(os.devnull, 'wb') if self.quiet_mode else None - subprocess.call(new_command, shell=(len(new_command) == 1), env=self.process_env, stdout=stdout) + + if self.kill_running: + if self.command_process and self.command_process.poll() == None: + self.kill_command_process() + self.command_process = subprocess.Popen(new_command, shell=(len(new_command) == 1), \ + env=self.process_env, stdout=stdout, preexec_fn=os.setsid) + else: + subprocess.call(new_command, shell=(len(new_command) == 1), env=self.process_env, stdout=stdout) self.last_run = time.time() def is_interested(self, path): @@ -158,6 +171,11 @@ def set_envvar(self, name, value): def get_envvar(self, name): return self.process_env['WHEN_CHANGED_' + name.upper()] + def kill_command_process(self): + if self.command_process: + pgid = os.getpgid(self.command_process.pid) + os.killpg(pgid, signal.SIGTERM) + def run(self): if self.run_at_start: self.run_command('/dev/null') @@ -168,9 +186,9 @@ def run(self): time.sleep(60 * 60) except KeyboardInterrupt: self.observer.stop() + self.kill_command_process() self.observer.join() - def print_usage(prog): print(__doc__ % {'prog': prog}, end='') @@ -190,6 +208,7 @@ def main(): run_once = False run_at_start = False quiet_mode = False + kill_running = False while args and args[0][0] == '-': flag = args.pop(0) @@ -210,6 +229,8 @@ def main(): args = [] elif flag == '-q': quiet_mode = True + elif flag == '-k': + kill_running = True else: break @@ -238,7 +259,7 @@ def main(): print("When '%s' changes, run '%s'" % (files[0], print_command)) wc = WhenChanged(files, command, recursive, run_once, run_at_start, - verbose_mode, quiet_mode) + verbose_mode, quiet_mode, kill_running) try: wc.run() From 460619f7977e0820db1e6b207e7ee9461651f8ae Mon Sep 17 00:00:00 2001 From: Jay Pratt Date: Wed, 28 Feb 2024 10:40:33 +1100 Subject: [PATCH 2/2] Fix for unset env var --- whenchanged/whenchanged.py | 1 + 1 file changed, 1 insertion(+) diff --git a/whenchanged/whenchanged.py b/whenchanged/whenchanged.py index 3611361..b3ee6b1 100755 --- a/whenchanged/whenchanged.py +++ b/whenchanged/whenchanged.py @@ -178,6 +178,7 @@ def kill_command_process(self): def run(self): if self.run_at_start: + self.set_envvar('event', 'start') self.run_command('/dev/null') self.observer.start()