-
Notifications
You must be signed in to change notification settings - Fork 7
/
blocked.go
187 lines (151 loc) · 4.98 KB
/
blocked.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package gomodguard
import (
"fmt"
"strings"
"github.com/Masterminds/semver/v3"
)
// Blocked is a list of modules that are
// blocked and not to be used.
type Blocked struct {
Modules BlockedModules `yaml:"modules"`
Versions BlockedVersions `yaml:"versions"`
LocalReplaceDirectives bool `yaml:"local_replace_directives"`
}
// BlockedVersion has a version constraint a reason why the module version is blocked.
type BlockedVersion struct {
Version string `yaml:"version"`
Reason string `yaml:"reason"`
}
// IsLintedModuleVersionBlocked returns true if a version constraint is specified and the
// linted module version matches the constraint.
func (r *BlockedVersion) IsLintedModuleVersionBlocked(lintedModuleVersion string) (bool, error) {
if r.Version == "" {
return false, nil
}
constraint, err := semver.NewConstraint(r.Version)
if err != nil {
return true, err
}
version, err := semver.NewVersion(lintedModuleVersion)
if err != nil {
return true, err
}
return constraint.Check(version), nil
}
// Message returns the reason why the module version is blocked.
func (r *BlockedVersion) Message(lintedModuleVersion string) string {
var sb strings.Builder
// Add version contraint to message.
_, _ = fmt.Fprintf(&sb, "version `%s` is blocked because it does not meet the version constraint `%s`.",
lintedModuleVersion, r.Version)
if r.Reason == "" {
return sb.String()
}
// Add reason to message.
_, _ = fmt.Fprintf(&sb, " %s.", strings.TrimRight(r.Reason, "."))
return sb.String()
}
// BlockedModule has alternative modules to use and a reason why the module is blocked.
type BlockedModule struct {
Recommendations []string `yaml:"recommendations"`
Reason string `yaml:"reason"`
}
// IsCurrentModuleARecommendation returns true if the current module is in the Recommendations list.
//
// If the current go.mod file being linted is a recommended module of a
// blocked module and it imports that blocked module, do not set as blocked.
// This could mean that the linted module is a wrapper for that blocked module.
func (r *BlockedModule) IsCurrentModuleARecommendation(currentModuleName string) bool {
if r == nil {
return false
}
for n := range r.Recommendations {
if strings.TrimSpace(currentModuleName) == strings.TrimSpace(r.Recommendations[n]) {
return true
}
}
return false
}
// Message returns the reason why the module is blocked and a list of recommended modules if provided.
func (r *BlockedModule) Message() string {
var sb strings.Builder
// Add recommendations to message
for i := range r.Recommendations {
switch {
case len(r.Recommendations) == 1:
_, _ = fmt.Fprintf(&sb, "`%s` is a recommended module.", r.Recommendations[i])
case (i+1) != len(r.Recommendations) && (i+1) == (len(r.Recommendations)-1):
_, _ = fmt.Fprintf(&sb, "`%s` ", r.Recommendations[i])
case (i + 1) != len(r.Recommendations):
_, _ = fmt.Fprintf(&sb, "`%s`, ", r.Recommendations[i])
default:
_, _ = fmt.Fprintf(&sb, "and `%s` are recommended modules.", r.Recommendations[i])
}
}
if r.Reason == "" {
return sb.String()
}
// Add reason to message
if sb.Len() == 0 {
_, _ = fmt.Fprintf(&sb, "%s.", strings.TrimRight(r.Reason, "."))
} else {
_, _ = fmt.Fprintf(&sb, " %s.", strings.TrimRight(r.Reason, "."))
}
return sb.String()
}
// HasRecommendations returns true if the blocked package has
// recommended modules.
func (r *BlockedModule) HasRecommendations() bool {
if r == nil {
return false
}
return len(r.Recommendations) > 0
}
// BlockedVersions a list of blocked modules by a version constraint.
type BlockedVersions []map[string]BlockedVersion
// Get returns the module names that are blocked.
func (b BlockedVersions) Get() []string {
modules := make([]string, len(b))
for n := range b {
for module := range b[n] {
modules[n] = module
break
}
}
return modules
}
// GetBlockReason returns a block version if one is set for the provided linted module name.
func (b BlockedVersions) GetBlockReason(lintedModuleName string) *BlockedVersion {
for _, blockedModule := range b {
for blockedModuleName, blockedVersion := range blockedModule {
if strings.TrimSpace(lintedModuleName) == strings.TrimSpace(blockedModuleName) {
return &blockedVersion
}
}
}
return nil
}
// BlockedModules a list of blocked modules.
type BlockedModules []map[string]BlockedModule
// Get returns the module names that are blocked.
func (b BlockedModules) Get() []string {
modules := make([]string, len(b))
for n := range b {
for module := range b[n] {
modules[n] = module
break
}
}
return modules
}
// GetBlockReason returns a block module if one is set for the provided linted module name.
func (b BlockedModules) GetBlockReason(lintedModuleName string) *BlockedModule {
for _, blockedModule := range b {
for blockedModuleName, blockedModule := range blockedModule {
if strings.TrimSpace(lintedModuleName) == strings.TrimSpace(blockedModuleName) {
return &blockedModule
}
}
}
return nil
}