diff --git a/internal/lefthook/run.go b/internal/lefthook/run.go index 002968eb..5e51143a 100644 --- a/internal/lefthook/run.go +++ b/internal/lefthook/run.go @@ -12,7 +12,7 @@ import ( "time" "github.com/evilmartians/lefthook/internal/config" - "github.com/evilmartians/lefthook/internal/lefthook/run" + "github.com/evilmartians/lefthook/internal/lefthook/runner" "github.com/evilmartians/lefthook/internal/log" "github.com/evilmartians/lefthook/internal/version" ) @@ -117,7 +117,7 @@ Run 'lefthook install' manually.`, } startTime := time.Now() - resultChan := make(chan run.Result, len(hook.Commands)+len(hook.Scripts)) + resultChan := make(chan runner.Result, len(hook.Commands)+len(hook.Scripts)) if args.FilesFromStdin { paths, err := io.ReadAll(os.Stdin) @@ -133,21 +133,6 @@ Run 'lefthook install' manually.`, args.Files = append(args.Files, files...) } - runner := run.NewRunner( - run.Options{ - Repo: l.repo, - Hook: hook, - HookName: hookName, - GitArgs: gitArgs, - ResultChan: resultChan, - LogSettings: logSettings, - DisableTTY: cfg.NoTTY || args.NoTTY, - Files: args.Files, - Force: args.Force, - RunOnlyCommands: args.RunOnlyCommands, - }, - ) - sourceDirs := []string{ filepath.Join(l.repo.RootPath, cfg.SourceDir), filepath.Join(l.repo.RootPath, cfg.SourceDirLocal), @@ -169,12 +154,27 @@ Run 'lefthook install' manually.`, ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() + r := runner.New( + runner.Options{ + Repo: l.repo, + Hook: hook, + HookName: hookName, + GitArgs: gitArgs, + ResultChan: resultChan, + LogSettings: logSettings, + DisableTTY: cfg.NoTTY || args.NoTTY, + Files: args.Files, + Force: args.Force, + RunOnlyCommands: args.RunOnlyCommands, + }, + ) + go func() { - runner.RunAll(ctx, sourceDirs) + r.RunAll(ctx, sourceDirs) close(resultChan) }() - var results []run.Result + var results []runner.Result for res := range resultChan { results = append(results, res) } @@ -186,7 +186,7 @@ Run 'lefthook install' manually.`, printSummary(time.Since(startTime), results, logSettings) for _, result := range results { - if result.Status == run.StatusErr { + if result.Err != nil { return errors.New("") // No error should be printed } } @@ -196,7 +196,7 @@ Run 'lefthook install' manually.`, func printSummary( duration time.Duration, - results []run.Result, + results []runner.Result, logSettings log.Settings, ) { if logSettings.LogSummary() { @@ -227,7 +227,7 @@ func printSummary( if logSettings.LogSuccess() { for _, result := range results { - if result.Status != run.StatusOk { + if result.Err != nil { continue } @@ -237,13 +237,13 @@ func printSummary( if logSettings.LogFailure() { for _, result := range results { - if result.Status != run.StatusErr { + if result.Err == nil { continue } - var failText string - if len(result.Text) != 0 { - failText = fmt.Sprintf(": %s", result.Text) + failText := result.Err.Error() + if len(failText) != 0 { + failText = fmt.Sprintf(": %s", failText) } log.Infof("🥊 %s%s\n", log.Red(result.Name), log.Red(failText)) diff --git a/internal/lefthook/run/result.go b/internal/lefthook/run/result.go deleted file mode 100644 index f245c94d..00000000 --- a/internal/lefthook/run/result.go +++ /dev/null @@ -1,20 +0,0 @@ -package run - -const ( - StatusOk status = iota - StatusErr -) - -type Result struct { - Name string - Text string - Status status -} - -func resultSuccess(name string) Result { - return Result{Name: name, Status: StatusOk} -} - -func resultFail(name, text string) Result { - return Result{Name: name, Text: text, Status: StatusErr} -} diff --git a/internal/lefthook/run/exec/execute_unix.go b/internal/lefthook/runner/exec/execute_unix.go similarity index 100% rename from internal/lefthook/run/exec/execute_unix.go rename to internal/lefthook/runner/exec/execute_unix.go diff --git a/internal/lefthook/run/exec/execute_windows.go b/internal/lefthook/runner/exec/execute_windows.go similarity index 100% rename from internal/lefthook/run/exec/execute_windows.go rename to internal/lefthook/runner/exec/execute_windows.go diff --git a/internal/lefthook/run/exec/executor.go b/internal/lefthook/runner/exec/executor.go similarity index 100% rename from internal/lefthook/run/exec/executor.go rename to internal/lefthook/runner/exec/executor.go diff --git a/internal/lefthook/run/exec/nullReader.go b/internal/lefthook/runner/exec/nullReader.go similarity index 100% rename from internal/lefthook/run/exec/nullReader.go rename to internal/lefthook/runner/exec/nullReader.go diff --git a/internal/lefthook/run/filter/filters.go b/internal/lefthook/runner/filter/filters.go similarity index 100% rename from internal/lefthook/run/filter/filters.go rename to internal/lefthook/runner/filter/filters.go diff --git a/internal/lefthook/run/filter/filters_test.go b/internal/lefthook/runner/filter/filters_test.go similarity index 100% rename from internal/lefthook/run/filter/filters_test.go rename to internal/lefthook/runner/filter/filters_test.go diff --git a/internal/lefthook/run/prepare_command.go b/internal/lefthook/runner/prepare_command.go similarity index 98% rename from internal/lefthook/run/prepare_command.go rename to internal/lefthook/runner/prepare_command.go index 3f285369..e1b3cc77 100644 --- a/internal/lefthook/run/prepare_command.go +++ b/internal/lefthook/runner/prepare_command.go @@ -1,4 +1,4 @@ -package run +package runner import ( "errors" @@ -9,7 +9,7 @@ import ( "gopkg.in/alessio/shellescape.v1" "github.com/evilmartians/lefthook/internal/config" - "github.com/evilmartians/lefthook/internal/lefthook/run/filter" + "github.com/evilmartians/lefthook/internal/lefthook/runner/filter" "github.com/evilmartians/lefthook/internal/log" ) diff --git a/internal/lefthook/run/prepare_command_test.go b/internal/lefthook/runner/prepare_command_test.go similarity index 99% rename from internal/lefthook/run/prepare_command_test.go rename to internal/lefthook/runner/prepare_command_test.go index 4eb7bb18..c4ead4e9 100644 --- a/internal/lefthook/run/prepare_command_test.go +++ b/internal/lefthook/runner/prepare_command_test.go @@ -1,4 +1,4 @@ -package run +package runner import ( "fmt" diff --git a/internal/lefthook/run/prepare_script.go b/internal/lefthook/runner/prepare_script.go similarity index 98% rename from internal/lefthook/run/prepare_script.go rename to internal/lefthook/runner/prepare_script.go index be3da607..1e971993 100644 --- a/internal/lefthook/run/prepare_script.go +++ b/internal/lefthook/runner/prepare_script.go @@ -1,4 +1,4 @@ -package run +package runner import ( "errors" diff --git a/internal/lefthook/run/runner.go b/internal/lefthook/runner/runner.go similarity index 97% rename from internal/lefthook/run/runner.go rename to internal/lefthook/runner/runner.go index 265fa2e4..fbfff985 100644 --- a/internal/lefthook/run/runner.go +++ b/internal/lefthook/runner/runner.go @@ -1,4 +1,4 @@ -package run +package runner import ( "bytes" @@ -22,13 +22,11 @@ import ( "github.com/evilmartians/lefthook/internal/config" "github.com/evilmartians/lefthook/internal/git" - "github.com/evilmartians/lefthook/internal/lefthook/run/exec" - "github.com/evilmartians/lefthook/internal/lefthook/run/filter" + "github.com/evilmartians/lefthook/internal/lefthook/runner/exec" + "github.com/evilmartians/lefthook/internal/lefthook/runner/filter" "github.com/evilmartians/lefthook/internal/log" ) -type status int8 - const ( executableFileMode os.FileMode = 0o751 executableMask os.FileMode = 0o111 @@ -59,7 +57,13 @@ type Runner struct { executor exec.Executor } -func NewRunner(opts Options) *Runner { +// Result contains name of a command/script and an optional fail string. +type Result struct { + Name string + Err error +} + +func New(opts Options) *Runner { return &Runner{ Options: opts, executor: exec.CommandExecutor{}, @@ -107,12 +111,12 @@ func (r *Runner) RunAll(ctx context.Context, sourceDirs []string) { } func (r *Runner) fail(name string, err error) { - r.ResultChan <- resultFail(name, err.Error()) + r.ResultChan <- Result{Name: name, Err: err} r.failed.Store(true) } func (r *Runner) success(name string) { - r.ResultChan <- resultSuccess(name) + r.ResultChan <- Result{Name: name, Err: nil} } func (r *Runner) runLFSHook(ctx context.Context) error { diff --git a/internal/lefthook/run/runner_test.go b/internal/lefthook/runner/runner_test.go similarity index 91% rename from internal/lefthook/run/runner_test.go rename to internal/lefthook/runner/runner_test.go index dea1b2fd..29711bae 100644 --- a/internal/lefthook/run/runner_test.go +++ b/internal/lefthook/runner/runner_test.go @@ -1,4 +1,4 @@ -package run +package runner import ( "context" @@ -15,7 +15,7 @@ import ( "github.com/evilmartians/lefthook/internal/config" "github.com/evilmartians/lefthook/internal/git" - "github.com/evilmartians/lefthook/internal/lefthook/run/exec" + "github.com/evilmartians/lefthook/internal/lefthook/runner/exec" "github.com/evilmartians/lefthook/internal/log" ) @@ -120,7 +120,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - success: []Result{{Name: "test", Status: StatusOk}}, + success: []Result{{Name: "test"}}, }, { name: "with simple command in follow mode", @@ -134,7 +134,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - success: []Result{{Name: "test", Status: StatusOk}}, + success: []Result{{Name: "test"}}, }, { name: "with multiple commands ran in parallel", @@ -155,10 +155,10 @@ func TestRunAll(t *testing.T) { Scripts: map[string]*config.Script{}, }, success: []Result{ - {Name: "test", Status: StatusOk}, - {Name: "lint", Status: StatusOk}, + {Name: "test"}, + {Name: "lint"}, }, - fail: []Result{{Name: "type-check", Status: StatusErr}}, + fail: []Result{{Name: "type-check", Err: errors.New("")}}, }, { name: "with exclude tags", @@ -180,7 +180,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - success: []Result{{Name: "lint", Status: StatusOk}}, + success: []Result{{Name: "lint"}}, }, { name: "with skip boolean option", @@ -197,7 +197,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - success: []Result{{Name: "lint", Status: StatusOk}}, + success: []Result{{Name: "lint"}}, }, { name: "with skip merge", @@ -217,7 +217,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - success: []Result{{Name: "lint", Status: StatusOk}}, + success: []Result{{Name: "lint"}}, }, { name: "with only on merge", @@ -238,8 +238,8 @@ func TestRunAll(t *testing.T) { Scripts: map[string]*config.Script{}, }, success: []Result{ - {Name: "lint", Status: StatusOk}, - {Name: "test", Status: StatusOk}, + {Name: "lint"}, + {Name: "test"}, }, }, { @@ -257,7 +257,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - success: []Result{{Name: "lint", Status: StatusOk}}, + success: []Result{{Name: "lint"}}, }, { name: "with global skip merge", @@ -315,8 +315,8 @@ func TestRunAll(t *testing.T) { Scripts: map[string]*config.Script{}, }, success: []Result{ - {Name: "lint", Status: StatusOk}, - {Name: "test", Status: StatusOk}, + {Name: "lint"}, + {Name: "test"}, }, }, { @@ -338,7 +338,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - success: []Result{{Name: "lint", Status: StatusOk}}, + success: []Result{{Name: "lint"}}, }, { name: "with global skip on ref", @@ -381,8 +381,8 @@ func TestRunAll(t *testing.T) { Scripts: map[string]*config.Script{}, }, success: []Result{ - {Name: "lint", Status: StatusOk}, - {Name: "test", Status: StatusOk}, + {Name: "lint"}, + {Name: "test"}, }, }, { @@ -426,8 +426,8 @@ func TestRunAll(t *testing.T) { Scripts: map[string]*config.Script{}, }, success: []Result{ - {Name: "test", Status: StatusOk}, - {Name: "lint", Status: StatusOk}, + {Name: "test"}, + {Name: "lint"}, }, }, { @@ -442,7 +442,7 @@ func TestRunAll(t *testing.T) { }, Scripts: map[string]*config.Script{}, }, - fail: []Result{{Name: "test", Status: StatusErr, Text: "try 'success'"}}, + fail: []Result{{Name: "test", Err: errors.New("try 'success'")}}, }, { name: "with simple scripts", @@ -464,8 +464,8 @@ func TestRunAll(t *testing.T) { }, }, }, - success: []Result{{Name: "script.sh", Status: StatusOk}}, - fail: []Result{{Name: "failing.js", Status: StatusErr, Text: "install node"}}, + success: []Result{{Name: "script.sh"}}, + fail: []Result{{Name: "failing.js", Err: errors.New("install node")}}, }, { name: "with simple scripts and only option", @@ -490,8 +490,8 @@ func TestRunAll(t *testing.T) { }, }, }, - success: []Result{{Name: "script.sh", Status: StatusOk}}, - fail: []Result{{Name: "failing.js", Status: StatusErr, Text: "install node"}}, + success: []Result{{Name: "script.sh"}}, + fail: []Result{{Name: "failing.js", Err: errors.New("install node")}}, }, { name: "with simple scripts and only option", @@ -548,7 +548,7 @@ func TestRunAll(t *testing.T) { }, }, success: []Result{}, // script.sh and ok are skipped - fail: []Result{{Name: "failing.js", Status: StatusErr}, {Name: "fail", Status: StatusErr}}, + fail: []Result{{Name: "failing.js", Err: errors.New("")}, {Name: "fail", Err: errors.New("")}}, }, { name: "with stage_fixed in true", @@ -580,8 +580,8 @@ func TestRunAll(t *testing.T) { }, }, }, - success: []Result{{Name: "ok", Status: StatusOk}, {Name: "success.sh", Status: StatusOk}}, - fail: []Result{{Name: "fail", Status: StatusErr}, {Name: "failing.js", Status: StatusErr}}, + success: []Result{{Name: "ok"}, {Name: "success.sh"}}, + fail: []Result{{Name: "fail", Err: errors.New("")}, {Name: "failing.js", Err: errors.New("")}}, }, { name: "pre-commit hook simple", @@ -615,8 +615,8 @@ func TestRunAll(t *testing.T) { }, }, }, - success: []Result{{Name: "ok", Status: StatusOk}, {Name: "success.sh", Status: StatusOk}}, - fail: []Result{{Name: "fail", Status: StatusErr}, {Name: "failing.js", Status: StatusErr}}, + success: []Result{{Name: "ok"}, {Name: "success.sh"}}, + fail: []Result{{Name: "fail", Err: errors.New("")}, {Name: "failing.js", Err: errors.New("")}}, gitCommands: []string{ "git status --short", "git diff --name-only --cached --diff-filter=ACMR", @@ -649,7 +649,7 @@ func TestRunAll(t *testing.T) { }, }, }, - success: []Result{{Name: "ok", Status: StatusOk}}, + success: []Result{{Name: "ok"}}, gitCommands: []string{ "git status --short", "git diff --name-only --cached --diff-filter=ACMR", @@ -681,8 +681,8 @@ func TestRunAll(t *testing.T) { }, }, force: true, - success: []Result{{Name: "ok", Status: StatusOk}}, - fail: []Result{{Name: "fail", Status: StatusErr}}, + success: []Result{{Name: "ok"}}, + fail: []Result{{Name: "fail", Err: errors.New("")}}, gitCommands: []string{ "git status --short", "git diff --name-only --cached --diff-filter=ACMR", @@ -707,7 +707,7 @@ func TestRunAll(t *testing.T) { }, }, }, - success: []Result{{Name: "ok", Status: StatusOk}}, + success: []Result{{Name: "ok"}}, gitCommands: []string{ "git status --short", "git diff --name-only --cached --diff-filter=ACMR", @@ -737,7 +737,7 @@ func TestRunAll(t *testing.T) { }, }, }, - success: []Result{{Name: "ok", Status: StatusOk}}, + success: []Result{{Name: "ok"}}, gitCommands: []string{ "git diff --name-only HEAD @{push}", "git diff --name-only HEAD @{push}", @@ -783,7 +783,7 @@ func TestRunAll(t *testing.T) { var success, fail []Result for res := range resultChan { - if res.Status == StatusOk { + if res.Err == nil { success = append(success, res) } else { fail = append(fail, res) @@ -820,12 +820,12 @@ func resultsMatch(a, b []Result) bool { matches := make(map[string]struct{}) for _, item := range a { - str := fmt.Sprintf("%s_%d_%s", item.Name, item.Status, item.Text) + str := fmt.Sprintf("%s_%v", item.Name, item.Err) matches[str] = struct{}{} } for _, item := range b { - str := fmt.Sprintf("%s_%d_%s", item.Name, item.Status, item.Text) + str := fmt.Sprintf("%s_%v", item.Name, item.Err) if _, ok := matches[str]; !ok { return false } diff --git a/testdata/fail_text.txt b/testdata/fail_text.txt new file mode 100644 index 00000000..509f3bc3 --- /dev/null +++ b/testdata/fail_text.txt @@ -0,0 +1,16 @@ +exec git init +exec git config user.email "you@example.com" +exec git config user.name "Your Name" +exec git add -A +exec lefthook install +! exec git commit -m 'test' +stderr '\s*fails: no such command\s*' + +-- lefthook.yml -- +output: + - failure +pre-commit: + commands: + fails: + run: oops-no-such-command + fail_text: no such command