Help language development. Donate to The Perl Foundation

Overwatch zef:tony-o last updated on 2021-08-09

bin/overwatch
#!/usr/bin/env raku

use overwatch;

sub MAIN (
  Str :e(:$execute) = 'raku',
  Bool :k(:$keep-alive) = True, 
  Bool :x(:$exit-on-error) = False, 
  Int  :g(:$git) = -1,
  Bool :q(:$quiet) = False,
  Str :f(:$filter) = '',
  :w(:$watch) = [],
  :p(:$pargs) = [],
  :s(:$sleep) = 1,
  *@args, 
) {

  my overwatch $overwatch;

  USAGE if @args.elems == 0;
  exit 0 if @args.elems == 0;

  $overwatch .=new(
    :$execute,
    :$keep-alive,
    :$exit-on-error,
    :$git,
    :$quiet,
    :$filter,
    :$sleep,
    watch => [|$watch],
  );

  if !$quiet {
    $overwatch.events.tap(-> $event {
      try {
        given $event<action> {
          when 'start' {
            '[INFO] Starting overseer with options:'.say;
            "[INFO]   --execute: {$event<execute>}".say;
            "[INFO]   --restart: {$event<execute>}".say;
            "[INFO]   --filters: {$event<filters>.join(', ')}".say;
            "[INFO]     --watch: {$event<watch>.join(', ')}".say;
            "[INFO]     --sleep: {$event<sleep>.join(', ')}".say;
            "[INFO]       --git: {$event<git-interval> <= 0 ?? 'disabled' !! "{$event<git-interval>}m"}".say;
            "[INFO]      script: {$event<args>.map({ "'$_'" }).join(' ')}".say;
          }
          when 'error' {
            "[ERROR] {$event<msg>}".say;
          }
          when 'file-changed' {
            "[ERROR] Restarting process, file changed: {$event<file-path>}".say;
          }
          when 'git-pull' {
            '[INFO] Pulling from remote repository'.say;
          }
          when 'kill-proc' {
            "[INFO] Killing process with {$event<signal>}".say;
          }
          when 'proc-died' {
            "[INFO] Exit code ({$event<code>}) caught, exiting".say;
          }
          when 'restart' {
            "[INFO] Restarting {$event<execute>}".say;
          }
        }
        CATCH { default { .say; } }
      }
    });
  }

  $overwatch.go([|$pargs, |@args]);
}

sub USAGE {
  my $space = ' ' x 4;
  say qq|Raku Overwatch can be used to restart programs when they crash or 
when files are modified.  

Usage: 
{$space}overwatch [options] <program> [<program arguments>]
    
Required:
{$space}<program>
{$space x 2}A program/script name is required.

Options:
{$space}-e=<executable> \| --execute=<executable>
{$space x 2}Default: 'raku'
{$space x 2}The executable that runs the specified <program>.

{$space}-k \| --keep-alive
{$space x 2}Default: True
{$space x 2}Automatically rerun the program.
 
{$space}-x \| --exit-on-error
{$space x 2}Default: False
{$space x 2}Stop overwatch if the <program> exited with a
{$space x 2}non-zero code.

{$space}-g \| --git
{$space x 2}Default: 0
{$space x 2}Checks default upstream git repository and pulls
{$space x 2}if local is behind. 
{$space x 2}A value of zero or less disables this option.

{$space}-q \| --quiet
{$space x 2}Default: False
{$space x 2}Prevents overwatch from printing informative
{$space x 2}messages to stdout. 

{$space}-w \| --watch
{$space x 2}Default: []
{$space x 2}Directories/files to watch for changes, when a
{$space x 2}file is changed the <program> is restarted.

{$space}-f \| --filter
{$space x 2}Default: ''
{$space x 2}Comma separated list of file extensions to watch
{$space x 2}for changes.  List applies to all --watch dirs.

{$space}-p \| --pargs
{$space x 2}Default: []
{$space x 2}List of arguments to start "-e" with.
{$space x 2}IE: overwatch -p="-e" "sleep 5"
{$space x 2}Would monitor the process: raku -e "sleep 5"

Notes:
{$space}Multiple -w switches may be specified
{$space}To negate a [True\|False} value you can use -/q (same as -q=False)

Examples:
{$space}overwatch app.pl6
{$space}overwatch -w=models mvc.pl6
{$space}overwatch -w=/tmp/ -e=/bin/sh shellscript.sh --shellarg=go
|

}