From 5e2509cb09ee94348cda8f68f3e1ed9091430c03 Mon Sep 17 00:00:00 2001 From: kurtisvg <31518063+kurtisvg@users.noreply.github.com> Date: Fri, 21 Aug 2020 12:20:55 -0700 Subject: [PATCH] fix: Print results on sigint/sigterm. --- cmd/common.go | 1 - cmd/run.go | 42 ++++++++++++++++-------------------------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/cmd/common.go b/cmd/common.go index 490f30e..12663ac 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -23,7 +23,6 @@ import ( const ( FailedCmdExitCode = 2 MisuseExitCode = 50 - InterruptExitCode = 51 ) // exitError is a typed error to return. diff --git a/cmd/run.go b/cmd/run.go index d64a602..9909f98 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -17,6 +17,7 @@ package cmd import ( "bytes" "context" + "errors" "fmt" "io" "os" @@ -45,12 +46,12 @@ a file that matches the specified pattern will have the command executed with a working directory of that folder. Output from each command and a summary of all commands run will be printed once execution completes`), Args: cobra.MinimumNArgs(2), - RunE: runRunWrapper, + RunE: runRun, } var ( - gitDiffArgs string - interactive bool + gitDiffArgs string + interactive bool maxConcurrently int ) @@ -65,36 +66,22 @@ func init() { "Limits the number of directories run max-concurrency. Defaults to 3 time the physical number of cores.") } -// runRunWrapper wraps runRun while watching for sigint/sigterm signals -func runRunWrapper(cmd *cobra.Command, args []string) error { +func runRun(cmd *cobra.Command, args []string) error { ctx := contextWithSignalCancel(context.Background()) - done := make(chan error) - go runRun(ctx, cmd, args, done) - select { - case r := <-done: - return r - case <-ctx.Done(): - return exitWithCode(InterruptExitCode, fmt.Errorf("execution interrupted")) - } -} -func runRun(ctx context.Context, cmd *cobra.Command, args []string, rtn chan<- error) { pattern := args[0] execCmd, err := shlex.Split(strings.Join(args[1:], " ")) if err != nil { - rtn <- exitWithCode(MisuseExitCode, err) - return + return exitWithCode(MisuseExitCode, err) } cmd.Print("Collecting directories that match pattern...") matches, err := rGlob(pattern) if err != nil { - rtn <- exitWithCode(MisuseExitCode, err) - return + return exitWithCode(MisuseExitCode, err) } if len(matches) == 0 { - rtn <- exitWithCode(MisuseExitCode, fmt.Errorf("no paths match pattern: '%s'", pattern)) - return + return exitWithCode(MisuseExitCode, fmt.Errorf("no paths match pattern: '%s'", pattern)) } // From the matching files, reduce to unique directories dirs, hist := []string{}, map[string]bool{} @@ -113,8 +100,7 @@ func runRun(ctx context.Context, cmd *cobra.Command, args []string, rtn chan<- e cmd.Printf(statusFmt, 0, len(dirs)) args, err := shlex.Split(gitDiffArgs) if err != nil { - rtn <- exitWithCode(MisuseExitCode, err) - return + return exitWithCode(MisuseExitCode, err) } results := startInDirs(ctx, maxConcurrently, append([]string{"git", "diff", "--exit-code"}, args...), dirs) // Wait for runs to complete, updating the user periodically @@ -143,7 +129,6 @@ func runRun(ctx context.Context, cmd *cobra.Command, args []string, rtn chan<- e } } - statusFmt := "Running command(s)... [%d of %d complete]." cmd.Printf(statusFmt, 0, len(dirs)) results := startInDirs(ctx, maxConcurrently, execCmd, dirs) @@ -202,9 +187,10 @@ func runRun(ctx context.Context, cmd *cobra.Command, args []string, rtn chan<- e if ct[Failure] > 0 || ct[Error] > 0 { // this non-zero exitcode is expected, so don't show usage cmd.SilenceErrors, cmd.SilenceUsage = true, true - rtn <- exitWithCode(FailedCmdExitCode, nil) + return exitWithCode(FailedCmdExitCode, nil) } - rtn <- nil // Completed successfully! + + return nil // Completed successfully! } // startInDirs starts a command running in multiple directories. @@ -238,6 +224,10 @@ func runInDir(ctx context.Context, execCmd []string, r *runResult) { r.Err = cmd.Run() if _, ok := r.Err.(*exec.ExitError); r.Err != nil && !ok { r.Status = Error // If it's not an exit error, the command failed to run + // A canceled context means that a sigint or sigterm was received + if r.Err == context.Canceled { + r.Err = errors.New("interupted before complete (sigint or sigterm)") + } r.Err = fmt.Errorf("failed to run cmd (%s): %w", strings.Join(cmd.Args, " "), r.Err) return }