Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev: clean up Executor #4404

Merged
merged 45 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
126988e
chore: remove deprecated flags
ldez Feb 18, 2024
d0eb53b
chore: re-organize methods and functions
ldez Feb 18, 2024
8db073c
chore: clean dead code
ldez Feb 18, 2024
62dd1a8
chore: re-organize comments related to cache
ldez Feb 18, 2024
1e2ba1f
chore: unify fonction naming
ldez Feb 18, 2024
865d6ea
chore: move BuildInfo to version
ldez Feb 18, 2024
d917656
fix: reports default flag values into defaultLintersSettings
ldez Feb 19, 2024
b7b86a6
chore: reformat some comments
ldez Feb 20, 2024
14bc543
chore(presets): converts methods to functions
ldez Feb 20, 2024
86be410
chore: same receiver for all Manager methods
ldez Feb 20, 2024
aaa99dc
chore: unexports some fields
ldez Feb 20, 2024
6076083
chore: move getConfigForCommandLine to executor file
ldez Feb 20, 2024
eaecfbd
chore: converts FlagSet methods to functions
ldez Feb 20, 2024
0bfebae
chore: linarize initVersionConfiguration
ldez Feb 20, 2024
4157048
chore: reformat some comments
ldez Feb 20, 2024
d1d6731
chore: isolate initHashSalt
ldez Feb 20, 2024
d938dae
chore: isolate init methods
ldez Feb 20, 2024
f8ff68d
chore: remove first call to lintersdb.NewManager from NewExecutor
ldez Feb 20, 2024
2b271d2
chore: move initCommands at the begining of NewExecutor
ldez Feb 20, 2024
34269cb
chore: isolate Executor initialization code
ldez Feb 20, 2024
ea79bbc
chore: fix imports
ldez Feb 20, 2024
fae562c
chore: reorganize initRunFlagSet
ldez Feb 20, 2024
7cc7c45
chore: remove useless needVersionOption method
ldez Feb 20, 2024
dfa6eb8
chore: inline help linters command
ldez Feb 20, 2024
13682c2
chore: reorganize initXX methods
ldez Feb 20, 2024
9b6eabd
chore: reorganize command methods
ldez Feb 20, 2024
283946f
chore: documment cmd fields
ldez Feb 20, 2024
1e8a199
chore: remove loadGuard field
ldez Feb 20, 2024
34572a8
chore: group executor fields
ldez Feb 20, 2024
18935d2
chore: clean goutil.Env
ldez Feb 20, 2024
b5b2a79
chore: remove sw and pkgCache fields
ldez Feb 20, 2024
f470c2c
chore: fixSlicesFlags before NewManager
ldez Feb 20, 2024
e7a19c7
chore: extract initConfiguration from initExecutor
ldez Feb 20, 2024
d995415
chore: remove Deadline tests
ldez Feb 20, 2024
9159274
chore: converts initHashSalt from methods to function
ldez Feb 20, 2024
51c1ee6
chore: removes useless flags from config command
ldez Feb 20, 2024
7a0bc08
chore: fix typos
ldez Feb 20, 2024
074c369
chore(offtopic): rename a variable inside NewGochecknoglobals
ldez Feb 20, 2024
3e97d56
chore(offtopic): extract govet validation from FileReader
ldez Feb 20, 2024
3b27685
chore: isolate Version field in Config
ldez Feb 20, 2024
c1d711d
chore: use errors.As
ldez Feb 20, 2024
858a41c
chore: annotate and re-organize configuration structures
ldez Feb 21, 2024
bfccfbd
chore: fix typo
ldez Feb 21, 2024
33416b2
fix: govet settings validation
ldez Feb 21, 2024
a3618d7
chore: remove allPresets function
ldez Feb 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions pkg/commands/cache.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package commands

import (
"bytes"
"crypto/sha256"
"fmt"
"io"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
"gopkg.in/yaml.v3"

"github.com/golangci/golangci-lint/internal/cache"
"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/fsutils"
"github.com/golangci/golangci-lint/pkg/logutils"
)
Expand Down Expand Up @@ -60,6 +66,68 @@ func (e *Executor) executeCacheStatus(_ *cobra.Command, _ []string) {
}
}

func (e *Executor) initHashSalt(version string) error {
binSalt, err := computeBinarySalt(version)
if err != nil {
return fmt.Errorf("failed to calculate binary salt: %w", err)
}

configSalt, err := computeConfigSalt(e.cfg)
if err != nil {
return fmt.Errorf("failed to calculate config salt: %w", err)
}

b := bytes.NewBuffer(binSalt)
b.Write(configSalt)
cache.SetSalt(b.Bytes())
return nil
}

func computeBinarySalt(version string) ([]byte, error) {
if version != "" && version != "(devel)" {
return []byte(version), nil
}

if logutils.HaveDebugTag(logutils.DebugKeyBinSalt) {
return []byte("debug"), nil
}

p, err := os.Executable()
if err != nil {
return nil, err
}
f, err := os.Open(p)
if err != nil {
return nil, err
}
defer f.Close()
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return nil, err
}
return h.Sum(nil), nil
}

func computeConfigSalt(cfg *config.Config) ([]byte, error) {
// We don't hash all config fields to reduce meaningless cache
// invalidations. At least, it has a huge impact on tests speed.

lintersSettingsBytes, err := yaml.Marshal(cfg.LintersSettings)
if err != nil {
return nil, fmt.Errorf("failed to json marshal config linter settings: %w", err)
}

configData := bytes.NewBufferString("linters-settings=")
configData.Write(lintersSettingsBytes)
configData.WriteString("\nbuild-tags=%s" + strings.Join(cfg.Run.BuildTags, ","))

h := sha256.New()
if _, err := h.Write(configData.Bytes()); err != nil {
return nil, err
}
return h.Sum(nil), nil
}

func dirSizeBytes(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
Expand Down
128 changes: 26 additions & 102 deletions pkg/commands/executor.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
package commands

import (
"bytes"
"context"
"crypto/sha256"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"

"github.com/fatih/color"
"github.com/gofrs/flock"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"gopkg.in/yaml.v3"

"github.com/golangci/golangci-lint/internal/cache"
"github.com/golangci/golangci-lint/internal/pkgcache"
"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/fsutils"
Expand Down Expand Up @@ -163,103 +154,36 @@ func (e *Executor) Execute() error {
return e.rootCmd.Execute()
}

func (e *Executor) initHashSalt(version string) error {
binSalt, err := computeBinarySalt(version)
if err != nil {
return fmt.Errorf("failed to calculate binary salt: %w", err)
}

configSalt, err := computeConfigSalt(e.cfg)
if err != nil {
return fmt.Errorf("failed to calculate config salt: %w", err)
}

b := bytes.NewBuffer(binSalt)
b.Write(configSalt)
cache.SetSalt(b.Bytes())
return nil
}

func computeBinarySalt(version string) ([]byte, error) {
if version != "" && version != "(devel)" {
return []byte(version), nil
}

if logutils.HaveDebugTag(logutils.DebugKeyBinSalt) {
return []byte("debug"), nil
}

p, err := os.Executable()
if err != nil {
return nil, err
}
f, err := os.Open(p)
if err != nil {
return nil, err
}
defer f.Close()
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return nil, err
}
return h.Sum(nil), nil
}

func computeConfigSalt(cfg *config.Config) ([]byte, error) {
// We don't hash all config fields to reduce meaningless cache
// invalidations. At least, it has a huge impact on tests speed.

lintersSettingsBytes, err := yaml.Marshal(cfg.LintersSettings)
if err != nil {
return nil, fmt.Errorf("failed to json marshal config linter settings: %w", err)
}

configData := bytes.NewBufferString("linters-settings=")
configData.Write(lintersSettingsBytes)
configData.WriteString("\nbuild-tags=%s" + strings.Join(cfg.Run.BuildTags, ","))

h := sha256.New()
if _, err := h.Write(configData.Bytes()); err != nil {
return nil, err
}
return h.Sum(nil), nil
}
func fixSlicesFlags(fs *pflag.FlagSet) {
// It's a dirty hack to set flag.Changed to true for every string slice flag.
// It's necessary to merge config and command-line slices: otherwise command-line
// flags will always overwrite ones from the config.
fs.VisitAll(func(f *pflag.Flag) {
if f.Value.Type() != "stringSlice" {
return
}

func (e *Executor) acquireFileLock() bool {
if e.cfg.Run.AllowParallelRunners {
e.debugf("Parallel runners are allowed, no locking")
return true
}
s, err := fs.GetStringSlice(f.Name)
if err != nil {
return
}

lockFile := filepath.Join(os.TempDir(), "golangci-lint.lock")
e.debugf("Locking on file %s...", lockFile)
f := flock.New(lockFile)
const retryDelay = time.Second
if s == nil { // assume that every string slice flag has nil as the default
return
}

ctx := context.Background()
if !e.cfg.Run.AllowSerialRunners {
const totalTimeout = 5 * time.Second
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, totalTimeout)
defer cancel()
}
if ok, _ := f.TryLockContext(ctx, retryDelay); !ok {
return false
}
var safe []string
for _, v := range s {
// add quotes to escape comma because spf13/pflag use a CSV parser:
// https://github.com/spf13/pflag/blob/85dd5c8bc61cfa382fecd072378089d4e856579d/string_slice.go#L43
safe = append(safe, `"`+v+`"`)
}

e.flock = f
return true
// calling Set sets Changed to true: next Set calls will append, not overwrite
_ = f.Value.Set(strings.Join(safe, ","))
})
}

func (e *Executor) releaseFileLock() {
if e.cfg.Run.AllowParallelRunners {
return
}

if err := e.flock.Unlock(); err != nil {
e.debugf("Failed to unlock on file: %s", err)
}
if err := os.Remove(e.flock.Path()); err != nil {
e.debugf("Failed to remove lock file: %s", err)
}
func wh(text string) string {
ldez marked this conversation as resolved.
Show resolved Hide resolved
return color.GreenString(text)
}
54 changes: 27 additions & 27 deletions pkg/commands/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,33 +33,6 @@ func (e *Executor) initHelp() {
helpCmd.AddCommand(lintersHelpCmd)
}

func printLinterConfigs(lcs []*linter.Config) {
sort.Slice(lcs, func(i, j int) bool {
return lcs[i].Name() < lcs[j].Name()
})
for _, lc := range lcs {
altNamesStr := ""
if len(lc.AlternativeNames) != 0 {
altNamesStr = fmt.Sprintf(" (%s)", strings.Join(lc.AlternativeNames, ", "))
}

// If the linter description spans multiple lines, truncate everything following the first newline
linterDescription := lc.Linter.Desc()
firstNewline := strings.IndexRune(linterDescription, '\n')
if firstNewline > 0 {
linterDescription = linterDescription[:firstNewline]
}

deprecatedMark := ""
if lc.IsDeprecated() {
deprecatedMark = " [" + color.RedString("deprecated") + "]"
}

fmt.Fprintf(logutils.StdOut, "%s%s%s: %s [fast: %t, auto-fix: %t]\n", color.YellowString(lc.Name()),
altNamesStr, deprecatedMark, linterDescription, !lc.IsSlowLinter(), lc.CanAutoFix)
}
}

func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) {
var enabledLCs, disabledLCs []*linter.Config
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
Expand Down Expand Up @@ -94,3 +67,30 @@ func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) {
fmt.Fprintf(logutils.StdOut, "%s: %s\n", color.YellowString(p), strings.Join(linterNames, ", "))
}
}

func printLinterConfigs(lcs []*linter.Config) {
sort.Slice(lcs, func(i, j int) bool {
return lcs[i].Name() < lcs[j].Name()
})
for _, lc := range lcs {
altNamesStr := ""
if len(lc.AlternativeNames) != 0 {
altNamesStr = fmt.Sprintf(" (%s)", strings.Join(lc.AlternativeNames, ", "))
}

// If the linter description spans multiple lines, truncate everything following the first newline
linterDescription := lc.Linter.Desc()
firstNewline := strings.IndexRune(linterDescription, '\n')
if firstNewline > 0 {
linterDescription = linterDescription[:firstNewline]
}

deprecatedMark := ""
if lc.IsDeprecated() {
deprecatedMark = " [" + color.RedString("deprecated") + "]"
}

fmt.Fprintf(logutils.StdOut, "%s%s%s: %s [fast: %t, auto-fix: %t]\n", color.YellowString(lc.Name()),
altNamesStr, deprecatedMark, linterDescription, !lc.IsSlowLinter(), lc.CanAutoFix)
}
}
Loading