1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package cache 6 7import ( 8 "fmt" 9 "io/ioutil" 10 "log" 11 "os" 12 "path/filepath" 13 "sync" 14) 15 16// Default returns the default cache to use. 17func Default() (*Cache, error) { 18 defaultOnce.Do(initDefaultCache) 19 return defaultCache, defaultDirErr 20} 21 22var ( 23 defaultOnce sync.Once 24 defaultCache *Cache 25) 26 27// cacheREADME is a message stored in a README in the cache directory. 28// Because the cache lives outside the normal Go trees, we leave the 29// README as a courtesy to explain where it came from. 30const cacheREADME = `This directory holds cached build artifacts from golangci-lint. 31` 32 33// initDefaultCache does the work of finding the default cache 34// the first time Default is called. 35func initDefaultCache() { 36 dir := DefaultDir() 37 if err := os.MkdirAll(dir, 0744); err != nil { 38 log.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) 39 } 40 if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { 41 // Best effort. 42 if wErr := ioutil.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666); wErr != nil { 43 log.Fatalf("Failed to write README file to cache dir %s: %s", dir, err) 44 } 45 } 46 47 c, err := Open(dir) 48 if err != nil { 49 log.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) 50 } 51 defaultCache = c 52} 53 54var ( 55 defaultDirOnce sync.Once 56 defaultDir string 57 defaultDirErr error 58) 59 60// DefaultDir returns the effective GOLANGCI_LINT_CACHE setting. 61func DefaultDir() string { 62 // Save the result of the first call to DefaultDir for later use in 63 // initDefaultCache. cmd/go/main.go explicitly sets GOCACHE so that 64 // subprocesses will inherit it, but that means initDefaultCache can't 65 // otherwise distinguish between an explicit "off" and a UserCacheDir error. 66 67 defaultDirOnce.Do(func() { 68 defaultDir = os.Getenv("GOLANGCI_LINT_CACHE") 69 if filepath.IsAbs(defaultDir) { 70 return 71 } 72 if defaultDir != "" { 73 defaultDirErr = fmt.Errorf("GOLANGCI_LINT_CACHE is not an absolute path") 74 return 75 } 76 77 // Compute default location. 78 dir, err := os.UserCacheDir() 79 if err != nil { 80 defaultDirErr = fmt.Errorf("GOLANGCI_LINT_CACHE is not defined and %v", err) 81 return 82 } 83 defaultDir = filepath.Join(dir, "golangci-lint") 84 }) 85 86 return defaultDir 87} 88