diff --git a/internal/config/command_executor.go b/internal/config/command_executor.go index d181f440..6a4781f0 100644 --- a/internal/config/command_executor.go +++ b/internal/config/command_executor.go @@ -2,6 +2,7 @@ package config import ( "io" + "os" "runtime" "github.com/evilmartians/lefthook/internal/system" @@ -25,7 +26,7 @@ func (c *commandExecutor) execute(commandLine string) bool { args = []string{"sh", "-c", commandLine} } - err := c.cmd.Run(args, "", system.NullReader, io.Discard) + err := c.cmd.Run(args, "", system.NullReader, io.Discard, os.Stderr) return err == nil } diff --git a/internal/config/skip_checker_test.go b/internal/config/skip_checker_test.go index 5b04f451..e5c263e8 100644 --- a/internal/config/skip_checker_test.go +++ b/internal/config/skip_checker_test.go @@ -10,7 +10,7 @@ import ( type mockCmd struct{} -func (mc mockCmd) Run(cmd []string, _root string, _in io.Reader, _out io.Writer) error { +func (mc mockCmd) Run(cmd []string, _root string, _in io.Reader, _out io.Writer, _errOut io.Writer) error { if len(cmd) == 3 && cmd[2] == "success" { return nil } else { diff --git a/internal/git/command_executor.go b/internal/git/command_executor.go index 64f12b36..cd4174a3 100644 --- a/internal/git/command_executor.go +++ b/internal/git/command_executor.go @@ -72,12 +72,17 @@ func (c CommandExecutor) CmdLinesWithinFolder(cmd []string, folder string) ([]st func (c CommandExecutor) execute(cmd []string, root string) (string, error) { out := new(bytes.Buffer) - err := c.cmd.Run(cmd, root, system.NullReader, out) - strOut := out.String() - - log.Debug("[lefthook] out: ", strOut) + errOut := new(bytes.Buffer) + err := c.cmd.Run(cmd, root, system.NullReader, out, errOut) + outString := out.String() + + log.Debug("[lefthook] stdout: ", outString) + errString := errOut.String() + if len(errString) > 0 { + log.Debug("[lefthook] stderr: ", errString) + } - return strOut, err + return outString, err } func batchByLength(s []string, length int) [][]string { diff --git a/internal/git/repository_test.go b/internal/git/repository_test.go index 3e2df8f2..89760179 100644 --- a/internal/git/repository_test.go +++ b/internal/git/repository_test.go @@ -12,7 +12,7 @@ type gitCmd struct { cases map[string]string } -func (g gitCmd) Run(cmd []string, _root string, _in io.Reader, out io.Writer) error { +func (g gitCmd) Run(cmd []string, _root string, _in io.Reader, out io.Writer, _errOut io.Writer) error { res, ok := g.cases[(strings.Join(cmd, " "))] if !ok { return errors.New("doesn't exist") diff --git a/internal/lefthook/run_test.go b/internal/lefthook/run_test.go index 0a223919..01a7c800 100644 --- a/internal/lefthook/run_test.go +++ b/internal/lefthook/run_test.go @@ -14,7 +14,7 @@ import ( type gitCmd struct{} -func (g gitCmd) Run([]string, string, io.Reader, io.Writer) error { +func (g gitCmd) Run([]string, string, io.Reader, io.Writer, io.Writer) error { return nil } diff --git a/internal/lefthook/runner/runner.go b/internal/lefthook/runner/runner.go index 622a8a0b..7579dc79 100644 --- a/internal/lefthook/runner/runner.go +++ b/internal/lefthook/runner/runner.go @@ -141,51 +141,63 @@ func (r *Runner) runLFSHook(ctx context.Context) error { return err } - if git.IsLFSAvailable() { - log.Debugf( - "[git-lfs] executing hook: git lfs %s %s", r.HookName, strings.Join(r.GitArgs, " "), - ) - out := new(bytes.Buffer) - err := r.cmd.RunWithContext( - ctx, - append( - []string{"git", "lfs", r.HookName}, - r.GitArgs..., - ), - "", - r.stdin, - out, - ) - - output := strings.Trim(out.String(), "\n") - if output != "" { - log.Debug("[git-lfs] out: ", output) - } - if err != nil { - log.Debug("[git-lfs] err: ", err) + if !git.IsLFSAvailable() { + if requiredExists || configExists { + log.Errorf( + "This Repository requires Git LFS, but 'git-lfs' wasn't found.\n"+ + "Install 'git-lfs' or consider reviewing the files:\n"+ + " - %s\n"+ + " - %s\n", + lfsRequiredFile, lfsConfigFile, + ) + return errors.New("git-lfs is required") } - if err == nil && output != "" { - log.Info(output) - } + return nil + } - if err != nil && (requiredExists || configExists) { - log.Warnf("git-lfs command failed: %s\n", output) - return err - } + log.Debugf( + "[git-lfs] executing hook: git lfs %s %s", r.HookName, strings.Join(r.GitArgs, " "), + ) + out := new(bytes.Buffer) + errOut := new(bytes.Buffer) + err = r.cmd.RunWithContext( + ctx, + append( + []string{"git", "lfs", r.HookName}, + r.GitArgs..., + ), + "", + r.stdin, + out, + errOut, + ) + + outString := strings.Trim(out.String(), "\n") + if outString != "" { + log.Debug("[git-lfs] stdout: ", outString) + } + errString := strings.Trim(errOut.String(), "\n") + if errString != "" { + log.Debug("[git-lfs] stderr: ", errString) + } + if err != nil { + log.Debug("[git-lfs] error: ", err) + } - return nil + if err == nil && outString != "" { + log.Info("[git-lfs] stdout: ", outString) } - if requiredExists || configExists { - log.Errorf( - "This Repository requires Git LFS, but 'git-lfs' wasn't found.\n"+ - "Install 'git-lfs' or consider reviewing the files:\n"+ - " - %s\n"+ - " - %s\n", - lfsRequiredFile, lfsConfigFile, - ) - return errors.New("git-lfs is required") + if err != nil && (requiredExists || configExists) { + log.Warn("git-lfs command failed") + if len(outString) > 0 { + log.Warn("[git-lfs] stdout: ", outString) + } + if len(errString) > 0 { + log.Warn("[git-lfs] stderr: ", errString) + } + return err } return nil diff --git a/internal/lefthook/runner/runner_test.go b/internal/lefthook/runner/runner_test.go index 295be378..2af044e6 100644 --- a/internal/lefthook/runner/runner_test.go +++ b/internal/lefthook/runner/runner_test.go @@ -38,11 +38,11 @@ func (e executor) Execute(_ctx context.Context, opts exec.Options, _in io.Reader return } -func (e cmd) RunWithContext(context.Context, []string, string, io.Reader, io.Writer) error { +func (e cmd) RunWithContext(context.Context, []string, string, io.Reader, io.Writer, io.Writer) error { return nil } -func (g *gitCmd) Run(cmd []string, _root string, _in io.Reader, out io.Writer) error { +func (g *gitCmd) Run(cmd []string, _root string, _in io.Reader, out io.Writer, _errOut io.Writer) error { g.mux.Lock() g.commands = append(g.commands, strings.Join(cmd, " ")) g.mux.Unlock() diff --git a/internal/system/system.go b/internal/system/system.go index ce5bf82b..4319d21c 100644 --- a/internal/system/system.go +++ b/internal/system/system.go @@ -15,44 +15,53 @@ type osCmd struct{} var Cmd = osCmd{} type Command interface { - Run([]string, string, io.Reader, io.Writer) error + Run([]string, string, io.Reader, io.Writer, io.Writer) error } type CommandWithContext interface { - RunWithContext(context.Context, []string, string, io.Reader, io.Writer) error + RunWithContext(context.Context, []string, string, io.Reader, io.Writer, io.Writer) error } // Run runs system command with LEFTHOOK=0 in order to prevent calling // subsequent lefthook hooks. -func (c osCmd) RunWithContext(ctx context.Context, command []string, root string, in io.Reader, out io.Writer) error { - log.Debug("[lefthook] cmd: ", command) +func (c osCmd) RunWithContext( + ctx context.Context, + command []string, + root string, + in io.Reader, + out io.Writer, + errOut io.Writer, +) error { + log.Debug("[lefthook] cmd: ", command) cmd := exec.CommandContext(ctx, command[0], command[1:]...) - return run(cmd, root, in, out) + return run(cmd, root, in, out, errOut) } -func (c osCmd) Run(command []string, root string, in io.Reader, out io.Writer) error { - log.Debug("[lefthook] cmd: ", command) +func (c osCmd) Run(command []string, root string, in io.Reader, out io.Writer, errOut io.Writer) error { + log.Debug("[lefthook] cmd: ", command) cmd := exec.Command(command[0], command[1:]...) - return run(cmd, root, in, out) + return run(cmd, root, in, out, errOut) } -func run(cmd *exec.Cmd, root string, in io.Reader, out io.Writer) error { +func run(cmd *exec.Cmd, root string, in io.Reader, out io.Writer, errOut io.Writer) error { cmd.Env = append(os.Environ(), "LEFTHOOK=0") if len(root) > 0 { cmd.Dir = root - log.Debug("[lefthook] dir: ", root) + log.Debug("[lefthook] dir: ", root) } cmd.Stdin = in cmd.Stdout = out - cmd.Stderr = os.Stderr + cmd.Stderr = errOut err := cmd.Run() - log.Debug("[lefthook] err: ", err) + if err != nil { + log.Debug("[lefthook] error: ", err) + } return err }