all repos — erl @ c8ab7c849959313a035bf9e448d110e794190a4f

Execute Reload Loop

initial commit

Alan Pearce
commit

c8ab7c849959313a035bf9e448d110e794190a4f

1 file changed, 107 insertions(+), 0 deletions(-)

changed files
A command/command.go
@@ -0,0 +1,107 @@
+package command + +import ( + "errors" + "fmt" + "io" + "os" + "os/exec" + "strings" + + "github.com/fatih/color" +) + +type Command interface { + Start() error + Wait() error + Stop() error +} + +type Cmd struct { + *exec.Cmd + + name string + args []string + + opts Options + + printFail func(string, ...any) + printSuccess func(string, ...any) +} + +type Options struct { + Stdout io.Writer + Stderr io.Writer +} + +func New(name string, args []string, options Options) *Cmd { + if options.Stdout == nil { + options.Stdout = os.Stdout + } + if options.Stderr == nil { + options.Stderr = os.Stderr + } + + return &Cmd{ + name: name, + args: args, + opts: options, + + printFail: color.New(color.FgRed).PrintfFunc(), + printSuccess: color.New(color.FgGreen).PrintfFunc(), + } +} + +func (cmd *Cmd) Stop() error { + if cmd.Cmd != nil && cmd.Process != nil && cmd.ProcessState == nil { + err := cmd.Process.Kill() + if err != nil { + return fmt.Errorf("error killing command: %v", err) + } + } + + return nil +} + +func (cmd *Cmd) Exited() bool { + return cmd.Cmd != nil && cmd.ProcessState != nil && cmd.ProcessState.Exited() +} + +func (cmd *Cmd) Wait() error { + err := cmd.Cmd.Wait() + if err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if cmd.Exited() { + cmd.printFail("[command exited with code %d]\n", cmd.ProcessState.ExitCode()) + } else { + cmd.printFail("[command stopped]\n") + } + } else { + return fmt.Errorf("error waiting for command: %v", err) + } + } + + if cmd.Exited() && cmd.ProcessState.Success() { + cmd.printSuccess("[command finished]\n") + } + + return nil +} + +func (cmd *Cmd) Start() error { + cmd.makeCommand() + cmd.printSuccess("[running: %s %s]\n", cmd.name, strings.Join(cmd.args, " ")) + err := cmd.Cmd.Start() + if err != nil { + return fmt.Errorf("error starting command: %v", err) + } + + return err +} + +func (cmd *Cmd) makeCommand() { + cmd.Cmd = exec.Command(cmd.name, cmd.args...) + cmd.Stdout = cmd.opts.Stdout + cmd.Stderr = cmd.opts.Stderr +}