Help language development. Donate to The Perl Foundation

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

#!/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,
) {

  my overwatch $overwatch;

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

  $overwatch .=new(
    watch => [|$watch],

  if !$quiet {
    $> $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.  

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

{$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"

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

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