• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evilmartians / lefthook / 13516253867

25 Feb 2025 07:54AM UTC coverage: 74.756% (-0.2%) from 74.971%
13516253867

push

github

web-flow
fix: remote issue with worktrees (#960)

6 of 29 new or added lines in 3 files covered. (20.69%)

3222 of 4310 relevant lines covered (74.76%)

3.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.36
/internal/git/command_executor.go
1
package git
2

3
import (
4
        "bytes"
5
        "fmt"
6
        "path/filepath"
7
        "strings"
8

9
        "github.com/evilmartians/lefthook/internal/log"
10
        "github.com/evilmartians/lefthook/internal/system"
11
)
12

13
// CommandExecutor provides some methods that take some effect on execution and/or result data.
14
type CommandExecutor struct {
15
        cmd  system.Command
16
        root string
17
}
18

19
// NewExecutor returns an object that executes given commands in the OS.
20
func NewExecutor(cmd system.Command) *CommandExecutor {
3✔
21
        return &CommandExecutor{cmd: cmd}
3✔
22
}
3✔
23

NEW
24
func (c CommandExecutor) WithEnvs(envs ...string) CommandExecutor {
×
NEW
25
        return CommandExecutor{cmd: c.cmd.WithEnvs(envs...), root: c.root}
×
NEW
26
}
×
27

28
// Cmd runs plain string command. Trims spaces around output.
29
func (c CommandExecutor) Cmd(cmd []string) (string, error) {
3✔
30
        out, err := c.execute(cmd, c.root)
3✔
31
        if err != nil {
5✔
32
                return "", err
2✔
33
        }
2✔
34

35
        return strings.TrimSpace(out), nil
3✔
36
}
37

38
// BatchedCmd runs the command with any number of appended arguments batched in chunks to match the OS limits.
39
func (c CommandExecutor) BatchedCmd(cmd []string, args []string) (string, error) {
3✔
40
        maxlen := system.MaxCmdLen()
3✔
41
        result := strings.Builder{}
3✔
42

3✔
43
        argsBatched := batchByLength(args, maxlen-len(cmd))
3✔
44
        for i, batch := range argsBatched {
6✔
45
                out, err := c.Cmd(append(cmd, batch...))
3✔
46
                if err != nil {
3✔
47
                        return "", fmt.Errorf("error in batch %d: %w", i, err)
×
48
                }
×
49
                result.WriteString(out)
3✔
50
                result.WriteString("\n")
3✔
51
        }
52

53
        return result.String(), nil
3✔
54
}
55

56
// CmdLines runs plain string command, returns its output split by newline.
57
func (c CommandExecutor) CmdLines(cmd []string) ([]string, error) {
6✔
58
        out, err := c.execute(cmd, c.root)
6✔
59
        if err != nil {
6✔
60
                return nil, err
×
61
        }
×
62

63
        return strings.Split(strings.TrimSpace(out), "\n"), nil
6✔
64
}
65

66
// CmdLines runs plain string command, returns its output split by newline.
67
func (c CommandExecutor) CmdLinesWithinFolder(cmd []string, folder string) ([]string, error) {
3✔
68
        root := filepath.Join(c.root, folder)
3✔
69
        out, err := c.execute(cmd, root)
3✔
70
        if err != nil {
3✔
71
                return nil, err
×
72
        }
×
73

74
        return strings.Split(strings.TrimSpace(out), "\n"), nil
3✔
75
}
76

77
func (c CommandExecutor) execute(cmd []string, root string) (string, error) {
6✔
78
        out := new(bytes.Buffer)
6✔
79
        errOut := new(bytes.Buffer)
6✔
80
        err := c.cmd.Run(cmd, root, system.NullReader, out, errOut)
6✔
81
        outString := out.String()
6✔
82

6✔
83
        log.Debug("[lefthook] stdout: ", outString)
6✔
84
        errString := errOut.String()
6✔
85
        if len(errString) > 0 {
8✔
86
                log.Debug("[lefthook] stderr: ", errString)
2✔
87
        }
2✔
88

89
        return outString, err
6✔
90
}
91

92
func batchByLength(s []string, length int) [][]string {
3✔
93
        batches := make([][]string, 0)
3✔
94

3✔
95
        var acc, prev int
3✔
96
        for i := range s {
6✔
97
                acc += len(s[i])
3✔
98
                if acc > length {
3✔
99
                        if i == prev {
×
100
                                batches = append(batches, s[prev:i+1])
×
101
                                prev = i + 1
×
102
                        } else {
×
103
                                batches = append(batches, s[prev:i])
×
104
                                prev = i
×
105
                        }
×
106
                        acc = len(s[i])
×
107
                }
108
        }
109
        if acc > 0 {
6✔
110
                batches = append(batches, s[prev:])
3✔
111
        }
3✔
112

113
        return batches
3✔
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc