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

evilmartians / lefthook / 17762708138

16 Sep 2025 10:23AM UTC coverage: 71.322% (-2.7%) from 73.996%
17762708138

push

github

web-flow
refactor: reduce the amount of code in a single file (#1131)

* refactor: reduce the amount of code in a single file

251 of 302 new or added lines in 5 files covered. (83.11%)

154 existing lines in 5 files now uncovered.

3457 of 4847 relevant lines covered (71.32%)

3.15 hits per line

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

84.13
/internal/config/script.go
1
package config
2

3
import (
4
        "cmp"
5
        "slices"
6
        "strconv"
7
        "strings"
8
        "unicode"
9

10
        "github.com/evilmartians/lefthook/internal/git"
11
        "github.com/evilmartians/lefthook/internal/system"
12
)
13

14
type Script struct {
15
        Runner string `json:"runner,omitempty" mapstructure:"runner" toml:"runner,omitempty" yaml:"runner,omitempty"`
16

17
        Skip     interface{}       `json:"skip,omitempty"     jsonschema:"oneof_type=boolean;array" mapstructure:"skip"       toml:"skip,omitempty,inline" yaml:",omitempty"`
18
        Only     interface{}       `json:"only,omitempty"     jsonschema:"oneof_type=boolean;array" mapstructure:"only"       toml:"only,omitempty,inline" yaml:",omitempty"`
19
        Tags     []string          `json:"tags,omitempty"     jsonschema:"oneof_type=string;array"  mapstructure:"tags"       toml:"tags,omitempty"        yaml:",omitempty"`
20
        Env      map[string]string `json:"env,omitempty"      mapstructure:"env"                    toml:"env,omitempty"      yaml:",omitempty"`
21
        Priority int               `json:"priority,omitempty" mapstructure:"priority"               toml:"priority,omitempty" yaml:",omitempty"`
22

23
        FailText    string `json:"fail_text,omitempty"   koanf:"fail_text"          mapstructure:"fail_text"     toml:"fail_text,omitempty"   yaml:"fail_text,omitempty"`
24
        Interactive bool   `json:"interactive,omitempty" mapstructure:"interactive" toml:"interactive,omitempty" yaml:",omitempty"`
25
        UseStdin    bool   `json:"use_stdin,omitempty"   koanf:"use_stdin"          mapstructure:"use_stdin"     toml:"use_stdin,omitempty"   yaml:"use_stdin,omitempty"`
26
        StageFixed  bool   `json:"stage_fixed,omitempty" koanf:"stage_fixed"        mapstructure:"stage_fixed"   toml:"stage_fixed,omitempty" yaml:"stage_fixed,omitempty"`
27
}
28

29
func (s Script) DoSkip(state func() git.State) bool {
×
30
        skipChecker := NewSkipChecker(system.Cmd)
×
31
        return skipChecker.Check(state, s.Skip, s.Only)
×
32
}
×
33

34
func ScriptsToJobs(scripts map[string]*Script) []*Job {
6✔
35
        jobs := make([]*Job, 0, len(scripts))
6✔
36
        for name, script := range scripts {
12✔
37
                jobs = append(jobs, &Job{
6✔
38
                        Name:        name,
6✔
39
                        Script:      name,
6✔
40
                        Runner:      script.Runner,
6✔
41
                        FailText:    script.FailText,
6✔
42
                        Tags:        script.Tags,
6✔
43
                        Env:         script.Env,
6✔
44
                        Interactive: script.Interactive,
6✔
45
                        UseStdin:    script.UseStdin,
6✔
46
                        StageFixed:  script.StageFixed,
6✔
47
                        Skip:        script.Skip,
6✔
48
                        Only:        script.Only,
6✔
49
                })
6✔
50
        }
6✔
51

52
        // ASC
53
        slices.SortFunc(jobs, func(i, j *Job) int {
9✔
54
                a := scripts[i.Name]
3✔
55
                b := scripts[j.Name]
3✔
56

3✔
57
                if a.Priority != 0 || b.Priority != 0 {
6✔
58
                        // Script without a priority must be the last
3✔
59
                        if a.Priority == 0 {
4✔
60
                                return 1
1✔
61
                        }
1✔
62
                        if b.Priority == 0 {
6✔
63
                                return -1
3✔
64
                        }
3✔
65

66
                        return cmp.Compare(a.Priority, b.Priority)
3✔
67
                }
68

69
                iNum := parseNum(i.Name)
3✔
70
                jNum := parseNum(j.Name)
3✔
71

3✔
72
                if iNum == -1 && jNum == -1 {
3✔
73
                        return strings.Compare(i.Name, j.Name)
×
74
                }
×
75

76
                if iNum == -1 {
6✔
77
                        return 1
3✔
78
                }
3✔
79

80
                if jNum == -1 {
3✔
UNCOV
81
                        return -1
×
UNCOV
82
                }
×
83

84
                return cmp.Compare(iNum, jNum)
3✔
85
        })
86

87
        return jobs
6✔
88
}
89

90
func parseNum(str string) int {
6✔
91
        numEnds := -1
6✔
92
        for idx, ch := range str {
12✔
93
                if unicode.IsDigit(ch) {
9✔
94
                        numEnds = idx
3✔
95
                } else {
9✔
96
                        break
6✔
97
                }
98
        }
99

100
        if numEnds == -1 {
12✔
101
                return -1
6✔
102
        }
6✔
103
        num, err := strconv.Atoi(str[:numEnds+1])
3✔
104
        if err != nil {
3✔
105
                return -1
×
106
        }
×
107

108
        return num
3✔
109
}
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