/
configuration.go
138 lines (105 loc) · 2.98 KB
/
configuration.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
package internal
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
)
const base = ".custom-gcl"
const defaultBinaryName = "custom-gcl"
// Configuration represents the configuration file.
type Configuration struct {
// golangci-lint version.
Version string `yaml:"version"`
// Name of the binary.
Name string `yaml:"name,omitempty"`
// Destination is the path to a directory to store the binary.
Destination string `yaml:"destination,omitempty"`
// Plugins information.
Plugins []*Plugin `yaml:"plugins,omitempty"`
}
// Validate checks and clean the configuration.
func (c *Configuration) Validate() error {
if strings.TrimSpace(c.Version) == "" {
return errors.New("root field 'version' is required")
}
if strings.TrimSpace(c.Name) == "" {
c.Name = defaultBinaryName
}
if len(c.Plugins) == 0 {
return errors.New("no plugins defined")
}
for _, plugin := range c.Plugins {
if strings.TrimSpace(plugin.Module) == "" {
return errors.New("field 'module' is required")
}
if strings.TrimSpace(plugin.Import) == "" {
plugin.Import = plugin.Module
}
if strings.TrimSpace(plugin.Path) == "" && strings.TrimSpace(plugin.Version) == "" {
return errors.New("missing information: 'version' or 'path' should be provided")
}
if strings.TrimSpace(plugin.Path) != "" && strings.TrimSpace(plugin.Version) != "" {
return errors.New("invalid configuration: 'version' and 'path' should not be provided at the same time")
}
if strings.TrimSpace(plugin.Path) == "" {
continue
}
abs, err := filepath.Abs(plugin.Path)
if err != nil {
return err
}
plugin.Path = abs
}
return nil
}
// Plugin represents information about a plugin.
type Plugin struct {
// Module name.
Module string `yaml:"module"`
// Import to use.
Import string `yaml:"import,omitempty"`
// Version of the module.
// Only for module available through a Go proxy.
Version string `yaml:"version,omitempty"`
// Path to the local module.
// Only for local module.
Path string `yaml:"path,omitempty"`
}
func LoadConfiguration() (*Configuration, error) {
configFilePath, err := findConfigurationFile()
if err != nil {
return nil, fmt.Errorf("file %s not found: %w", configFilePath, err)
}
file, err := os.Open(configFilePath)
if err != nil {
return nil, fmt.Errorf("file %s open: %w", configFilePath, err)
}
var cfg Configuration
err = yaml.NewDecoder(file).Decode(&cfg)
if err != nil {
return nil, fmt.Errorf("YAML decoding: %w", err)
}
return &cfg, nil
}
func findConfigurationFile() (string, error) {
entries, err := os.ReadDir(".")
if err != nil {
return "", fmt.Errorf("read directory: %w", err)
}
for _, entry := range entries {
ext := filepath.Ext(entry.Name())
switch strings.ToLower(strings.TrimPrefix(ext, ".")) {
case "yml", "yaml", "json":
if isConf(ext, entry.Name()) {
return entry.Name(), nil
}
}
}
return "", errors.New("configuration file not found")
}
func isConf(ext, name string) bool {
return base+ext == name
}