Home | History | Annotate | Download | only in cache
      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 	"io/ioutil"
     10 	"os"
     11 	"path/filepath"
     12 	"runtime"
     13 	"sync"
     14 )
     15 
     16 // Default returns the default cache to use, or nil if no cache should be used.
     17 func Default() *Cache {
     18 	defaultOnce.Do(initDefaultCache)
     19 	return defaultCache
     20 }
     21 
     22 var (
     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.
     30 const cacheREADME = `This directory holds cached build artifacts from the Go build system.
     31 Run "go clean -cache" if the directory is getting too large.
     32 See golang.org to learn more about Go.
     33 `
     34 
     35 // initDefaultCache does the work of finding the default cache
     36 // the first time Default is called.
     37 func initDefaultCache() {
     38 	dir := DefaultDir()
     39 	if dir == "off" {
     40 		return
     41 	}
     42 	if err := os.MkdirAll(dir, 0777); err != nil {
     43 		fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
     44 		return
     45 	}
     46 	if _, err := os.Stat(filepath.Join(dir, "README")); err != nil {
     47 		// Best effort.
     48 		ioutil.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666)
     49 	}
     50 
     51 	c, err := Open(dir)
     52 	if err != nil {
     53 		fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
     54 		return
     55 	}
     56 	defaultCache = c
     57 }
     58 
     59 // DefaultDir returns the effective GOCACHE setting.
     60 // It returns "off" if the cache is disabled.
     61 func DefaultDir() string {
     62 	dir := os.Getenv("GOCACHE")
     63 	if dir != "" {
     64 		return dir
     65 	}
     66 
     67 	// Compute default location.
     68 	// TODO(rsc): This code belongs somewhere else,
     69 	// like maybe ioutil.CacheDir or os.CacheDir.
     70 	switch runtime.GOOS {
     71 	case "windows":
     72 		dir = os.Getenv("LocalAppData")
     73 		if dir == "" {
     74 			// Fall back to %AppData%, the old name of
     75 			// %LocalAppData% on Windows XP.
     76 			dir = os.Getenv("AppData")
     77 		}
     78 		if dir == "" {
     79 			return "off"
     80 		}
     81 
     82 	case "darwin":
     83 		dir = os.Getenv("HOME")
     84 		if dir == "" {
     85 			return "off"
     86 		}
     87 		dir += "/Library/Caches"
     88 
     89 	case "plan9":
     90 		dir = os.Getenv("home")
     91 		if dir == "" {
     92 			return "off"
     93 		}
     94 		// Plan 9 has no established per-user cache directory,
     95 		// but $home/lib/xyz is the usual equivalent of $HOME/.xyz on Unix.
     96 		dir += "/lib/cache"
     97 
     98 	default: // Unix
     99 		// https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
    100 		dir = os.Getenv("XDG_CACHE_HOME")
    101 		if dir == "" {
    102 			dir = os.Getenv("HOME")
    103 			if dir == "" {
    104 				return "off"
    105 			}
    106 			dir += "/.cache"
    107 		}
    108 	}
    109 	return filepath.Join(dir, "go-build")
    110 }
    111