Implement no-restart-on option

This commit is contained in:
Max Claus Nunes 2018-06-19 01:19:04 -03:00
parent 68c9d713ae
commit 04b1615274
2 changed files with 42 additions and 14 deletions

View File

@ -45,10 +45,10 @@ GLOBAL OPTIONS:
--ignore value, -i value list of folders or files to ignore for changes --ignore value, -i value list of folders or files to ignore for changes
--poll-interval value, -p value how often in milliseconds to poll watched files for changes (default: 500) --poll-interval value, -p value how often in milliseconds to poll watched files for changes (default: 500)
--extensions value, -e value a comma-delimited list of file extensions to watch for changes (default: "go") --extensions value, -e value a comma-delimited list of file extensions to watch for changes (default: "go")
----no-restart-on value, -n value don't automatically restart the executed program if it ends. --no-restart-on value, -n value don't automatically restart the executed program if it ends:
If "error", an exit code of 0 will still restart. if "error", an exit code of 0 will still restart.
If "exit", no restart regardless of exit code. if "exit", no restart regardless of exit code.
If "success", no restart only if exit code is 0. if "success", no restart only if exit code is 0.
--help, -h show help --help, -h show help
--version, -v print the version --version, -v print the version
``` ```

48
main.go
View File

@ -15,9 +15,14 @@ import (
var logger = NewLogger("gaper") var logger = NewLogger("gaper")
// default values
var defaultExtensions = cli.StringSlice{"go"} var defaultExtensions = cli.StringSlice{"go"}
var defaultPoolInterval = 500 var defaultPoolInterval = 500
// exit statuses
var exitStatusSuccess = 0
var exitStatusError = 1
// Config ... // Config ...
type Config struct { type Config struct {
BinName string BinName string
@ -97,12 +102,12 @@ func main() {
Value: &defaultExtensions, Value: &defaultExtensions,
Usage: "a comma-delimited list of file extensions to watch for changes", Usage: "a comma-delimited list of file extensions to watch for changes",
}, },
cli.StringSliceFlag{ cli.StringFlag{
Name: "--no-restart-on, n", Name: "no-restart-on, n",
Usage: "don't automatically restart the supervised program if it ends.\n" + Usage: "don't automatically restart the supervised program if it ends:\n" +
"\t\tIf \"error\", an exit code of 0 will still restart.\n" + "\t\tif \"error\", an exit code of 0 will still restart.\n" +
"\t\tIf \"exit\", no restart regardless of exit code.\n" + "\t\tif \"exit\", no restart regardless of exit code.\n" +
"\t\tIf \"success\", no restart only if exit code is 0.", "\t\tif \"success\", no restart only if exit code is 0.",
}, },
} }
@ -146,8 +151,9 @@ func runGaper(cfg *Config) error {
logger.Debug(" | verbose: ", cfg.Verbose) logger.Debug(" | verbose: ", cfg.Verbose)
logger.Debug(" | watch: ", cfg.WatchItems) logger.Debug(" | watch: ", cfg.WatchItems)
logger.Debug(" | ignore: ", cfg.IgnoreItems) logger.Debug(" | ignore: ", cfg.IgnoreItems)
logger.Debug(" | poll-interval: ", cfg.PollInterval) logger.Debug(" | poll interval: ", cfg.PollInterval)
logger.Debug(" | extensions: ", cfg.Extensions) logger.Debug(" | extensions: ", cfg.Extensions)
logger.Debug(" | no restart on: ", cfg.NoRestartOn)
logger.Debug(" | working directory: ", wd) logger.Debug(" | working directory: ", wd)
builder := NewBuilder(cfg.BuildPath, cfg.BinName, wd, cfg.BuildArgs) builder := NewBuilder(cfg.BuildPath, cfg.BinName, wd, cfg.BuildArgs)
@ -184,7 +190,7 @@ func runGaper(cfg *Config) error {
changeRestart = false changeRestart = false
} else { } else {
logger.Debug("Detected program exit: ", err) logger.Debug("Detected program exit: ", err)
if err = handleProgramExit(builder, runner, err); err != nil { if err = handleProgramExit(builder, runner, err, cfg.NoRestartOn); err != nil {
return err return err
} }
} }
@ -215,12 +221,34 @@ func restart(builder Builder, runner Runner) error {
return nil return nil
} }
func handleProgramExit(builder Builder, runner Runner, err error) error { func handleProgramExit(builder Builder, runner Runner, err error, noRestartOn string) error {
_, ok := err.(*exec.ExitError) exiterr, ok := err.(*exec.ExitError)
if !ok { if !ok {
return fmt.Errorf("couldn't handle program crash restart: %v", err) return fmt.Errorf("couldn't handle program crash restart: %v", err)
} }
status, oks := exiterr.Sys().(syscall.WaitStatus)
if !oks {
return fmt.Errorf("couldn't resolve exit status: %v", err)
}
exitStatus := status.ExitStatus()
// if "error", an exit code of 0 will still restart.
if noRestartOn == "error" && exitStatus == exitStatusError {
return nil
}
// if "success", no restart only if exit code is 0.
if noRestartOn == "success" && exitStatus == exitStatusSuccess {
return nil
}
// if "exit", no restart regardless of exit code.
if noRestartOn == "exit" {
return nil
}
restart(builder, runner) restart(builder, runner)
return nil return nil
} }