Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: split files into chunks #541

Merged
merged 11 commits into from
Sep 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
.vscode/
.idea/
.lefthook-local/
.lefthook/
/lefthook-local.yml
/lefthook.yml
/lefthook

tmp/
Expand Down
15 changes: 15 additions & 0 deletions .lefthook.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[pre-commit]
parallel = true

[pre-commit.commands.lint]
run = "make lint"
glob = "*.go"
stage_fixed = true

[pre-commit.commands.test]
run = "make test"
glob = "*.go"

[pre-commit.commands.lychee]
glob = "*.md"
run = "lychee {staged_files}"
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ bin/golangci-lint:
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.54.1

lint: bin/golangci-lint
$$(go env GOPATH)/bin/golangci-lint run
$$(go env GOPATH)/bin/golangci-lint run --fix

.ONESHELL:
version:
Expand Down
2 changes: 1 addition & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ When you try to commit `git commit -m "haha bad commit text"` script `commitlint
### Parallel execution

You can enable parallel execution if you want to speed up your checks.
Lets get example from [discourse](https://github.com/discourse/discourse/blob/master/.travis.yml#L77-L83) project.
Lets imagine we have the following rules to lint the whole project:

```
bundle exec rubocop --parallel && \
Expand Down
21 changes: 10 additions & 11 deletions internal/lefthook/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"time"

"github.com/evilmartians/lefthook/internal/config"
"github.com/evilmartians/lefthook/internal/lefthook/runner"
"github.com/evilmartians/lefthook/internal/lefthook/run"
"github.com/evilmartians/lefthook/internal/log"
"github.com/evilmartians/lefthook/internal/version"
)
Expand Down Expand Up @@ -105,11 +105,10 @@ Run 'lefthook install' manually.`,
}

startTime := time.Now()
resultChan := make(chan runner.Result, len(hook.Commands)+len(hook.Scripts))
resultChan := make(chan run.Result, len(hook.Commands)+len(hook.Scripts))

run := runner.NewRunner(
runner.Opts{
Fs: l.Fs,
runner := run.NewRunner(
run.Options{
Repo: l.repo,
Hook: hook,
HookName: hookName,
Expand Down Expand Up @@ -140,11 +139,11 @@ Run 'lefthook install' manually.`,
}

go func() {
run.RunAll(sourceDirs)
runner.RunAll(sourceDirs)
close(resultChan)
}()

var results []runner.Result
var results []run.Result
for res := range resultChan {
results = append(results, res)
}
Expand All @@ -154,7 +153,7 @@ Run 'lefthook install' manually.`,
}

for _, result := range results {
if result.Status == runner.StatusErr {
if result.Status == run.StatusErr {
return errors.New("") // No error should be printed
}
}
Expand All @@ -164,7 +163,7 @@ Run 'lefthook install' manually.`,

func printSummary(
duration time.Duration,
results []runner.Result,
results []run.Result,
logSettings log.SkipSettings,
) {
if len(results) == 0 {
Expand All @@ -180,7 +179,7 @@ func printSummary(

if !logSettings.SkipSuccess() {
for _, result := range results {
if result.Status != runner.StatusOk {
if result.Status != run.StatusOk {
continue
}

Expand All @@ -190,7 +189,7 @@ func printSummary(

if !logSettings.SkipFailure() {
for _, result := range results {
if result.Status != runner.StatusErr {
if result.Status != run.StatusErr {
continue
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build !windows
// +build !windows

package runner
package exec

import (
"fmt"
Expand All @@ -19,36 +19,55 @@ import (

type CommandExecutor struct{}

func (e CommandExecutor) Execute(opts ExecuteOptions, out io.Writer) error {
stdin := os.Stdin
if opts.interactive && !isatty.IsTerminal(os.Stdin.Fd()) {
func (e CommandExecutor) Execute(opts Options, out io.Writer) error {
in := os.Stdin
if opts.Interactive && !isatty.IsTerminal(os.Stdin.Fd()) {
tty, err := os.Open("/dev/tty")
if err == nil {
defer tty.Close()
stdin = tty
in = tty
} else {
log.Errorf("Couldn't enable TTY input: %s\n", err)
}
}

command := exec.Command("sh", "-c", strings.Join(opts.args, " "))

rootDir, _ := filepath.Abs(opts.root)
command.Dir = rootDir

envList := make([]string, len(opts.env))
for name, value := range opts.env {
envList = append(
envList,
root, _ := filepath.Abs(opts.Root)
envs := make([]string, len(opts.Env))
for name, value := range opts.Env {
envs = append(
envs,
fmt.Sprintf("%s=%s", strings.ToUpper(name), os.ExpandEnv(value)),
)
}

command.Env = append(os.Environ(), envList...)
// We can have one command split into separate to fit into shell command max length.
// In this case we execute those commands one by one.
for _, args := range opts.Commands {
if err := e.executeOne(args, root, envs, opts.Interactive, in, out); err != nil {
return err
}
}

return nil
}

func (e CommandExecutor) RawExecute(command []string, out io.Writer) error {
cmd := exec.Command(command[0], command[1:]...)

cmd.Stdout = out
cmd.Stderr = os.Stderr

return cmd.Run()
}

func (e CommandExecutor) executeOne(args []string, root string, envs []string, interactive bool, in io.Reader, out io.Writer) error {
command := exec.Command("sh", "-c", strings.Join(args, " "))
command.Dir = root
command.Env = append(os.Environ(), envs...)

if opts.interactive {
if interactive {
command.Stdout = out
command.Stdin = stdin
command.Stdin = in
command.Stderr = os.Stderr
err := command.Start()
if err != nil {
Expand All @@ -62,7 +81,7 @@ func (e CommandExecutor) Execute(opts ExecuteOptions, out io.Writer) error {

defer func() { _ = p.Close() }()

go func() { _, _ = io.Copy(p, stdin) }()
go func() { _, _ = io.Copy(p, in) }()

_, _ = io.Copy(out, p)
}
Expand All @@ -71,12 +90,3 @@ func (e CommandExecutor) Execute(opts ExecuteOptions, out io.Writer) error {

return command.Wait()
}

func (e CommandExecutor) RawExecute(command []string, out io.Writer) error {
cmd := exec.Command(command[0], command[1:]...)

cmd.Stdout = out
cmd.Stderr = os.Stderr

return cmd.Run()
}
67 changes: 67 additions & 0 deletions internal/lefthook/run/exec/execute_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package exec

import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
)

type CommandExecutor struct{}

func (e CommandExecutor) Execute(opts Options, out io.Writer) error {
root, _ := filepath.Abs(opts.Root)
envs := make([]string, len(opts.Env))
for name, value := range opts.Env {
envs = append(
envs,
fmt.Sprintf("%s=%s", strings.ToUpper(name), os.ExpandEnv(value)),
)
}

for _, args := range opts.Commands {
if err := e.executeOne(args, root, envs, opts.Interactive, os.Stdin, out); err != nil {
return err
}
}

return nil
}

func (e CommandExecutor) RawExecute(command []string, out io.Writer) error {
cmd := exec.Command(command[0], command[1:]...)

cmd.Stdout = out
cmd.Stderr = os.Stderr

return cmd.Run()
}

func (e CommandExecutor) executeOne(args []string, root string, envs []string, interactive bool, in io.Reader, out io.Writer) error {
command := exec.Command(args[0])
command.SysProcAttr = &syscall.SysProcAttr{
CmdLine: strings.Join(args, " "),
}
command.Dir = root
command.Env = append(os.Environ(), envs...)

if interactive {
command.Stdout = os.Stdout
} else {
command.Stdout = out
}

command.Stdin = in
command.Stderr = os.Stderr
err := command.Start()
if err != nil {
return err
}

defer func() { _ = command.Process.Kill() }()

return command.Wait()
}
20 changes: 20 additions & 0 deletions internal/lefthook/run/exec/executor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package exec

import (
"io"
)

// Options contains the data that controls the execution.
type Options struct {
Name, Root, FailText string
Commands [][]string
Env map[string]string
Interactive bool
}

// Executor provides an interface for command execution.
// It is used here for testing purpose mostly.
type Executor interface {
Execute(opts Options, out io.Writer) error
RawExecute(command []string, out io.Writer) error
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
package runner
package filter

import (
"regexp"
"strings"

"github.com/gobwas/glob"

"github.com/evilmartians/lefthook/internal/config"
"github.com/evilmartians/lefthook/internal/log"
)

func filterGlob(vs []string, matcher string) []string {
func Apply(command *config.Command, files []string) []string {
if len(files) == 0 {
return nil
}

log.Debug("[lefthook] files before filters:\n", files)

files = byGlob(files, command.Glob)
files = byExclude(files, command.Exclude)
files = byRoot(files, command.Root)

log.Debug("[lefthook] files after filters:\n", files)

return files
}

func byGlob(vs []string, matcher string) []string {
if matcher == "" {
return vs
}
Expand All @@ -23,7 +42,7 @@ func filterGlob(vs []string, matcher string) []string {
return vsf
}

func filterExclude(vs []string, matcher string) []string {
func byExclude(vs []string, matcher string) []string {
if matcher == "" {
return vs
}
Expand All @@ -37,7 +56,7 @@ func filterExclude(vs []string, matcher string) []string {
return vsf
}

func filterRelative(vs []string, matcher string) []string {
func byRoot(vs []string, matcher string) []string {
if matcher == "" {
return vs
}
Expand Down
Loading
Loading