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

evilmartians / lefthook / 8504903245

01 Apr 2024 06:45AM UTC coverage: 81.325% (+3.4%) from 77.962%
8504903245

Pull #684

github

web-flow
Merge e09d0a9fa into 599459eb8
Pull Request #684: feat: add priorities to scripts

37 of 39 new or added lines in 3 files covered. (94.87%)

2 existing lines in 2 files now uncovered.

2565 of 3154 relevant lines covered (81.33%)

7.07 hits per line

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

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

3
import (
4
        "strings"
5

6
        "github.com/mitchellh/mapstructure"
7
        "github.com/spf13/viper"
8

9
        "github.com/evilmartians/lefthook/internal/git"
10
)
11

12
type Script struct {
13
        Runner string `json:"runner" mapstructure:"runner" toml:"runner" yaml:"runner"`
14

15
        Skip interface{}       `json:"skip,omitempty" mapstructure:"skip" toml:"skip,omitempty,inline" yaml:",omitempty"`
16
        Only interface{}       `json:"only,omitempty" mapstructure:"only" toml:"only,omitempty,inline" yaml:",omitempty"`
17
        Tags []string          `json:"tags,omitempty" mapstructure:"tags" toml:"tags,omitempty"        yaml:",omitempty"`
18
        Env  map[string]string `json:"env,omitempty"  mapstructure:"env"  toml:"env,omitempty"         yaml:",omitempty"`
19

20
        FailText    string `json:"fail_text,omitempty"   mapstructure:"fail_text"   toml:"fail_text,omitempty"   yaml:"fail_text,omitempty"`
21
        Interactive bool   `json:"interactive,omitempty" mapstructure:"interactive" toml:"interactive,omitempty" yaml:",omitempty"`
22
        UseStdin    bool   `json:"use_stdin,omitempty"   mapstructure:"use_stdin"   toml:"use_stdin,omitempty"   yaml:",omitempty"`
23
        StageFixed  bool   `json:"stage_fixed,omitempty" mapstructure:"stage_fixed" toml:"stage_fixed,omitempty" yaml:"stage_fixed,omitempty"`
24
}
25

26
func (s Script) DoSkip(gitState git.State) bool {
3✔
27
        skipChecker := NewSkipChecker(NewOsExec())
3✔
28
        return skipChecker.Check(gitState, s.Skip, s.Only)
3✔
29
}
3✔
30

31
type scriptRunnerReplace struct {
3✔
32
        Runner string `mapstructure:"runner"`
3✔
33
}
3✔
34

3✔
35
func mergeScripts(base, extra *viper.Viper) (map[string]*Script, error) {
6✔
36
        if base == nil && extra == nil {
6✔
NEW
37
                return nil, nil
×
UNCOV
38
        }
×
39

40
        if base == nil {
18✔
41
                return unmarshalScripts(extra.GetStringMap("scripts"))
12✔
42
        }
6✔
43

44
        if extra == nil {
6✔
45
                return unmarshalScripts(base.GetStringMap("scripts"))
12✔
46
        }
6✔
47

6✔
48
        scriptsOrigin := base.GetStringMap("scripts")
6✔
49
        scriptsOverride := extra.GetStringMap("scripts")
12✔
50
        if scriptsOrigin == nil {
6✔
51
                return unmarshalScripts(scriptsOverride)
×
52
        }
53
        if scriptsOverride == nil {
12✔
54
                return unmarshalScripts(scriptsOrigin)
6✔
55
        }
6✔
56

57
        runReplaces := make(map[string]*scriptRunnerReplace)
6✔
58
        for key, originConfig := range scriptsOrigin {
18✔
59
                var runReplace scriptRunnerReplace
6✔
60

6✔
61
                if err := unmarshal(originConfig, &runReplace); err != nil {
6✔
62
                        return nil, err
6✔
63
                }
12✔
64

6✔
65
                runReplaces[key] = &runReplace
12✔
66
        }
6✔
67

68
        err := base.MergeConfigMap(map[string]interface{}{
6✔
69
                "scripts": scriptsOverride,
6✔
70
        })
12✔
71
        if err != nil {
6✔
72
                return nil, err
73
        }
6✔
74

6✔
75
        scripts, err := unmarshalScripts(base.GetStringMap("scripts"))
12✔
76
        if err != nil {
12✔
77
                return nil, err
×
78
        }
×
79

80
        for key, replace := range runReplaces {
18✔
81
                if replace.Runner != "" {
18✔
82
                        scripts[key].Runner = strings.ReplaceAll(scripts[key].Runner, CMD, replace.Runner)
6✔
83
                }
6✔
84
        }
85

12✔
86
        return scripts, nil
18✔
87
}
6✔
88

6✔
89
func unmarshalScripts(s map[string]interface{}) (map[string]*Script, error) {
6✔
90
        if len(s) == 0 {
12✔
91
                return nil, nil
12✔
92
        }
6✔
93

94
        scripts := make(map[string]*Script)
12✔
95
        for name, scriptConfig := range s {
24✔
96
                var script Script
12✔
97

12✔
98
                if err := unmarshal(scriptConfig, &script); err != nil {
6✔
99
                        return nil, err
6✔
100
                }
12✔
101

6✔
102
                scripts[name] = &script
12✔
103
        }
6✔
104

105
        return scripts, nil
6✔
106
}
107

6✔
108
// `scripts` are unmarshalled manually because viper
109
// uses "." as a key delimiter. So, this definition:
110
//
6✔
111
// ```yaml
112
// scripts:
113
//
114
//        "example.sh":
115
//            runner: bash
116
//
117
// ```
118
//
119
// Unmarshals into this:
120
//
121
// ```yaml
122
// scripts:
123
//
124
//        example:
125
//          sh:
126
//            runner: bash
127
//
128
// ```
129
//
130
// This is not an expected behavior and cannot be controlled yet
131
// Working with GetStringMap is the only way to get the structure "as is".
132
func unmarshal(input, output interface{}) error {
6✔
133
        return mapstructure.WeakDecode(input, &output)
6✔
134
}
6✔
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

© 2025 Coveralls, Inc