golangci-lint/pkg/commands/internal/configuration.go
Fernandez Ludovic 7ad7949ca9 dev: close file
2024-04-16 13:19:31 +02:00

141 lines
3.0 KiB
Go

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)
}
defer func() { _ = file.Close() }()
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
}