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