11package commands
22
33import (
4+ "bytes"
5+ "crypto/sha256"
46 "fmt"
7+ "io"
58 "os"
69 "path/filepath"
10+ "strings"
711
812 "github.com/spf13/cobra"
13+ "gopkg.in/yaml.v3"
914
1015 "github.com/golangci/golangci-lint/internal/cache"
16+ "github.com/golangci/golangci-lint/pkg/config"
1117 "github.com/golangci/golangci-lint/pkg/fsutils"
1218 "github.com/golangci/golangci-lint/pkg/logutils"
1319)
@@ -21,14 +27,13 @@ func (e *Executor) initCache() {
2127 return cmd .Help ()
2228 },
2329 }
24- e .rootCmd .AddCommand (cacheCmd )
2530
2631 cacheCmd .AddCommand (& cobra.Command {
2732 Use : "clean" ,
2833 Short : "Clean cache" ,
2934 Args : cobra .NoArgs ,
3035 ValidArgsFunction : cobra .NoFileCompletions ,
31- RunE : e .executeCleanCache ,
36+ RunE : e .executeCacheClean ,
3237 })
3338 cacheCmd .AddCommand (& cobra.Command {
3439 Use : "status" ,
@@ -39,9 +44,11 @@ func (e *Executor) initCache() {
3944 })
4045
4146 // TODO: add trim command?
47+
48+ e .rootCmd .AddCommand (cacheCmd )
4249}
4350
44- func (e * Executor ) executeCleanCache (_ * cobra.Command , _ []string ) error {
51+ func (e * Executor ) executeCacheClean (_ * cobra.Command , _ []string ) error {
4552 cacheDir := cache .DefaultDir ()
4653 if err := os .RemoveAll (cacheDir ); err != nil {
4754 return fmt .Errorf ("failed to remove dir %s: %w" , cacheDir , err )
@@ -70,3 +77,68 @@ func dirSizeBytes(path string) (int64, error) {
7077 })
7178 return size , err
7279}
80+
81+ // --- Related to cache but not used directly by the cache command.
82+
83+ func initHashSalt (version string , cfg * config.Config ) error {
84+ binSalt , err := computeBinarySalt (version )
85+ if err != nil {
86+ return fmt .Errorf ("failed to calculate binary salt: %w" , err )
87+ }
88+
89+ configSalt , err := computeConfigSalt (cfg )
90+ if err != nil {
91+ return fmt .Errorf ("failed to calculate config salt: %w" , err )
92+ }
93+
94+ b := bytes .NewBuffer (binSalt )
95+ b .Write (configSalt )
96+ cache .SetSalt (b .Bytes ())
97+ return nil
98+ }
99+
100+ func computeBinarySalt (version string ) ([]byte , error ) {
101+ if version != "" && version != "(devel)" {
102+ return []byte (version ), nil
103+ }
104+
105+ if logutils .HaveDebugTag (logutils .DebugKeyBinSalt ) {
106+ return []byte ("debug" ), nil
107+ }
108+
109+ p , err := os .Executable ()
110+ if err != nil {
111+ return nil , err
112+ }
113+ f , err := os .Open (p )
114+ if err != nil {
115+ return nil , err
116+ }
117+ defer f .Close ()
118+ h := sha256 .New ()
119+ if _ , err := io .Copy (h , f ); err != nil {
120+ return nil , err
121+ }
122+ return h .Sum (nil ), nil
123+ }
124+
125+ // computeConfigSalt computes configuration hash.
126+ // We don't hash all config fields to reduce meaningless cache invalidations.
127+ // At least, it has a huge impact on tests speed.
128+ // Fields: `LintersSettings` and `Run.BuildTags`.
129+ func computeConfigSalt (cfg * config.Config ) ([]byte , error ) {
130+ lintersSettingsBytes , err := yaml .Marshal (cfg .LintersSettings )
131+ if err != nil {
132+ return nil , fmt .Errorf ("failed to json marshal config linter settings: %w" , err )
133+ }
134+
135+ configData := bytes .NewBufferString ("linters-settings=" )
136+ configData .Write (lintersSettingsBytes )
137+ configData .WriteString ("\n build-tags=%s" + strings .Join (cfg .Run .BuildTags , "," ))
138+
139+ h := sha256 .New ()
140+ if _ , err := h .Write (configData .Bytes ()); err != nil {
141+ return nil , err
142+ }
143+ return h .Sum (nil ), nil
144+ }
0 commit comments