diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..ffe1092 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,42 @@ +kind: pipeline +name: default + +steps: +- name: golangci-lint + image: golangci/golangci-lint:v1.49 + volumes: + - name: deps + path: /go/src/mod + commands: + - golangci-lint run --timeout 5m + +- name: test + image: golang + volumes: + - name: deps + path: /go/src/mod + commands: + - go test ./... + +- name: example golangci-lint + image: golangci/golangci-lint:v1.49 + volumes: + - name: deps + path: /go/src/mod + commands: + - cd scripts + - golangci-lint run --timeout 5m + +- name: example test + image: golang + volumes: + - name: deps + path: /go/src/mod + commands: + - cd scripts + - go test ./... + +volumes: +- name: deps + temp: {} + diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..80c0ba8 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,43 @@ +linters-settings: + dupl: + threshold: 100 + funlen: + lines: 100 + statements: 50 + goconst: + min-len: 2 + min-occurrences: 2 + gocyclo: + min-complexity: 15 + golint: + min-confidence: 0 + govet: + check-shadowing: true + lll: + line-length: 140 + maligned: + suggest-new: true + misspell: + locale: US + varnamelen: + min-name-length: 2 + +linters: + enable-all: true + disable: + - varcheck + - maligned + - scopelint + - nosnakecase + - ifshort + - golint + - interfacer + - structcheck + - deadcode + - exhaustivestruct + - exhaustruct + +# is disabled because of generics. You can track the evolution of the generics support by following the https://github.com/golangci/golangci-lint/issues/2649 + - rowserrcheck + - sqlclosecheck + - wastedassign diff --git a/mime.go b/mime.go index ca6c850..811cade 100644 --- a/mime.go +++ b/mime.go @@ -13,6 +13,7 @@ func (v Mime) Is(types ...Mime) bool { return true } } + return false } diff --git a/scripts/main.go b/scripts/main.go index e985a6d..5a9723e 100644 --- a/scripts/main.go +++ b/scripts/main.go @@ -11,8 +11,10 @@ import ( func main() { ctx, cancel := context.WithCancel(context.Background()) + closer.AddLast(func() error { cancel() + return nil }) diff --git a/scripts/mime/generate.go b/scripts/mime/generate.go index 8660338..1d71b1c 100644 --- a/scripts/mime/generate.go +++ b/scripts/mime/generate.go @@ -1,9 +1,9 @@ package mime import ( + "errors" "fmt" "go/format" - "io/ioutil" "os" "path" "text/template" @@ -11,6 +11,16 @@ import ( "gopkg.in/yaml.v3" ) +var ( + ErrDuplicate = errors.New("duplicate") + ErrNotFound = errors.New("not found") +) + +const ( + NameExt = "ext" + NameMime = "mime" +) + type Config struct { Source string @@ -33,6 +43,28 @@ type Data struct { Value []string `yaml:"value,omitempty"` } +func (c *Config) Base(name string) string { + switch name { + case NameExt: + return path.Base(c.ExtTpl) + case NameMime: + return path.Base(c.MimeTpl) + } + + return "" +} + +func (c *Config) Result(name string) string { + switch name { + case NameExt: + return c.ExtResult + case NameMime: + return c.MimeResult + } + + return "" +} + func (c *Config) ValidateAndFillExt() error { mimes := make(map[string]int) mimeIDs := make(map[int]string) @@ -40,7 +72,7 @@ func (c *Config) ValidateAndFillExt() error { for idx, ext := range c.Extensions { if _, ok := extIndex[ext.Name]; ok { - return fmt.Errorf("extension %v duplicate: with id %v", ext.Name, c.Extensions[extIndex[ext.Name]].ID) + return fmt.Errorf("extension %v %w: with id %v", ext.Name, ErrDuplicate, c.Extensions[extIndex[ext.Name]].ID) } extIndex[ext.Name] = idx @@ -48,22 +80,21 @@ func (c *Config) ValidateAndFillExt() error { for _, mime := range c.Mimes { if _, ok := mimes[mime.Name]; ok { - return fmt.Errorf("mime %v duplicate: with id %v", mime.Name, mimes[mime.Name]) + return fmt.Errorf("mime %v %w: with id %v", mime.Name, ErrDuplicate, mimes[mime.Name]) } if _, ok := mimeIDs[mime.ID]; ok { - return fmt.Errorf("ID %v duplicate: with name %v", mime.ID, mimeIDs[mime.ID]) + return fmt.Errorf("ID %v %w: with name %v", mime.ID, ErrDuplicate, mimeIDs[mime.ID]) } for _, ext := range mime.Value { idx, ok := extIndex[ext] if !ok { - return fmt.Errorf("not fount ext by %v", mime.Name) + return fmt.Errorf("%w ext by %v", ErrNotFound, mime.Name) } c.Extensions[idx].Value = append(c.Extensions[idx].Value, mime.Name) } - } return nil @@ -133,17 +164,17 @@ func Generate(fileName string, opts ...Option) error { opt(&cfg) } - data, err := os.ReadFile(fileName) - if err != nil { - return fmt.Errorf("read file:%w", err) + data, cerr := os.ReadFile(fileName) + if cerr != nil { + return fmt.Errorf("read file:%w", cerr) } - if err := yaml.Unmarshal(data, &cfg); err != nil { - return fmt.Errorf("unmarshal:%w", err) + if uerr := yaml.Unmarshal(data, &cfg); uerr != nil { + return fmt.Errorf("unmarshal:%w", uerr) } - if err := cfg.ValidateAndFillExt(); err != nil { - return fmt.Errorf("config:%w", err) + if validErr := cfg.ValidateAndFillExt(); validErr != nil { + return fmt.Errorf("config:%w", validErr) } template, err := template.New("mimes").Funcs(funcMap()).ParseFiles(cfg.ExtTpl, cfg.MimeTpl) @@ -151,30 +182,29 @@ func Generate(fileName string, opts ...Option) error { return fmt.Errorf("ext template:%w", err) } - extFile, err := os.Create(cfg.ExtResult) - if err != nil { - return fmt.Errorf("ext file:%w", err) + if exErr := Create(template, NameExt, cfg); exErr != nil { + return fmt.Errorf("ext create:%w", exErr) } - if err := template.ExecuteTemplate(extFile, path.Base(cfg.ExtTpl), cfg); err != nil { - return fmt.Errorf("ext execute:%w", err) + if mimeErr := Create(template, NameMime, cfg); mimeErr != nil { + return fmt.Errorf("mime create:%w", mimeErr) } - if err := Format(extFile.Name()); err != nil { - return fmt.Errorf("format ext:%w", err) - } + return nil +} - mimeFile, err := os.Create(cfg.MimeResult) +func Create(tpl *template.Template, name string, cfg Config) error { + extFile, err := os.Create(cfg.Result(name)) if err != nil { - return fmt.Errorf("mime file:%w", err) + return fmt.Errorf("ext file:%w", err) } - if err := template.ExecuteTemplate(mimeFile, path.Base(cfg.MimeTpl), cfg); err != nil { - return fmt.Errorf("mime execute:%w", err) + if exErr := tpl.ExecuteTemplate(extFile, cfg.Base(name), cfg); exErr != nil { + return fmt.Errorf("ext execute:%w", exErr) } - if err := Format(mimeFile.Name()); err != nil { - return fmt.Errorf("format mime:%w", err) + if formatErr := Format(extFile.Name()); formatErr != nil { + return fmt.Errorf("format ext:%w", formatErr) } return nil @@ -182,13 +212,14 @@ func Generate(fileName string, opts ...Option) error { // Format file and write it. func Format(name string) error { - in, err := ioutil.ReadFile(name) + in, err := os.ReadFile(name) if err != nil { - return err + return fmt.Errorf("read file:%w", err) } + out, err := format.Source(in) if err != nil { - return err + return fmt.Errorf("format source:%w", err) } file, err := os.Create(name) @@ -202,19 +233,3 @@ func Format(name string) error { return nil } - -func extensions(mimes map[string][]string) map[string][]string { - out := make(map[string][]string) - - for mime, exts := range mimes { - for _, ext := range exts { - if _, ok := out[ext]; ok { - out[ext] = append(out[ext], mime) - continue - } - out[ext] = []string{mime} - } - } - - return out -}