From 6cbdb29738104750cf3b4453dcf17fe4de6af69f Mon Sep 17 00:00:00 2001 From: Shpak Roman Date: Wed, 3 Jun 2020 01:05:01 +0300 Subject: [PATCH] Add modular output --- README.md | 14 +++++++++++ cmd/run.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index aa867acf..e29505fb 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,20 @@ fixer: $ lefthook run fixer ``` +* ### **Modular output** +If you want to display supporting information optionally: +```yml +output: + - meta #(version and which hook running) + - failures #(output from runners with exit code nonzero) + - success #(output from runners with exit code 0) + - summary #(summary block) +``` + +Or if you don't want to display supporting information: +```yml +output: false +``` --- diff --git a/cmd/run.go b/cmd/run.go index 8b303c89..aca203bf 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "log" "os" "os/exec" @@ -54,6 +55,11 @@ const ( filesConfigKey string = "files" colorsConfigKey string = "colors" parallelConfigKey string = "parallel" + outputConfigKey string = "output" + outputMeta string = "meta" + outputFailures string = "failures" + outputSuccess string = "success" + outputSummary string = "summary" subFiles string = "{files}" subAllFiles string = "{all_files}" subStagedFiles string = "{staged_files}" @@ -110,8 +116,7 @@ func RunCmdExecutor(args []string, fs afero.Fs) error { var wg sync.WaitGroup startTime := time.Now() - log.Println(au.Cyan("Lefthook v" + version)) - log.Println(au.Cyan("RUNNING HOOKS GROUP:"), au.Bold(hooksGroup)) + printMeta(hooksGroup) if isPipedAndParallel(hooksGroup) { log.Println(au.Brown("Config error! Conflicted options 'piped' and 'parallel'. Remove one of this option from hook group.")) @@ -146,7 +151,6 @@ func RunCmdExecutor(args []string, fs afero.Fs) error { commands := getCommands(hooksGroup) if len(commands) != 0 { - for _, commandName := range commands { wg.Add(1) if getParallel(hooksGroup) { @@ -257,12 +261,17 @@ func executeCommand(hooksGroup, commandName string, wg *sync.WaitGroup) { defer func() { ptyOut.Close() }() // Make sure to close the pty at the end. // Copy stdin to the pty and the pty to stdout. go func() { io.Copy(ptyOut, os.Stdin) }() - io.Copy(os.Stdout, ptyOut) + comandOutput, _ := ioutil.ReadAll(ptyOut) + ptyOut.Close() // pty part end if command.Wait() == nil { + printSuccess(comandOutput) + okList = append(okList, commandName) } else { + printFailure(comandOutput) + failList = append(failList, commandName) setPipeBroken() } @@ -337,12 +346,17 @@ func executeScript(hooksGroup, source string, executable os.FileInfo, wg *sync.W defer func() { ptyOut.Close() }() // Make sure to close the pty at the end. // Copy stdin to the pty and the pty to stdout. go func() { io.Copy(ptyOut, os.Stdin) }() - io.Copy(os.Stdout, ptyOut) + comandOutput, _ := ioutil.ReadAll(ptyOut) + ptyOut.Close() // pty part end if command.Wait() == nil { + printSuccess(comandOutput) + okList = append(okList, executableName) } else { + printFailure(comandOutput) + failList = append(failList, executableName) setPipeBroken() } @@ -374,7 +388,36 @@ func getRunner(hooksGroup, source, executableName string) string { return runner } +func printMeta(hooksGroup string) { + if isSkipPrintOutput(outputMeta) { + return + } + + log.Println(au.Cyan("Lefthook v" + version)) + log.Println(au.Cyan("RUNNING HOOKS GROUP:"), au.Bold(hooksGroup)) +} + +func printFailure(ptyOut []byte) { + if isSkipPrintOutput(outputFailures) { + return + } + + log.Println(string(ptyOut)) +} + +func printSuccess(ptyOut []byte) { + if isSkipPrintOutput(outputSuccess) { + return + } + + log.Println(string(ptyOut)) +} + func printSummary(execTime time.Duration) { + if isSkipPrintOutput(outputSummary) { + return + } + if len(okList) == 0 && len(failList) == 0 { log.Println(au.Cyan("\nSUMMARY:"), au.Brown("(SKIP EMPTY)")) } else { @@ -420,6 +463,24 @@ func isSkipEmptyCommmand(hooksGroup, executableName string) bool { return true } +func isSkipPrintOutput(outputDetailValue string) bool { + if !viper.IsSet(outputConfigKey) { + return false + } + + if viper.Get(outputConfigKey) == false { + return true + } + + for _, elem := range viper.GetStringSlice(outputConfigKey) { + if elem == outputDetailValue { + return false + } + } + + return true +} + func getCommands(hooksGroup string) []string { key := strings.Join([]string{hooksGroup, commandsConfigKey}, ".") commands := viper.GetStringMap(key)