New returns a new cache for the repo ID at basedir. If basedir is the empty string, the default cache location (according to the XDG standard) is used. For partial files, the complete file is loaded and stored in the cache when performReadahead returns true.
(id string, basedir string)
| 77 | // For partial files, the complete file is loaded and stored in the cache when |
| 78 | // performReadahead returns true. |
| 79 | func New(id string, basedir string) (c *Cache, err error) { |
| 80 | if basedir == "" { |
| 81 | basedir, err = DefaultDir() |
| 82 | if err != nil { |
| 83 | return nil, err |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | err = os.MkdirAll(basedir, dirMode) |
| 88 | if err != nil { |
| 89 | return nil, errors.WithStack(err) |
| 90 | } |
| 91 | |
| 92 | // create base dir and tag it as a cache directory |
| 93 | if err = writeCachedirTag(basedir); err != nil { |
| 94 | return nil, err |
| 95 | } |
| 96 | |
| 97 | cachedir := filepath.Join(basedir, id) |
| 98 | debug.Log("using cache dir %v", cachedir) |
| 99 | |
| 100 | created := false |
| 101 | v, err := readVersion(cachedir) |
| 102 | switch { |
| 103 | case err == nil: |
| 104 | if v > cacheVersion { |
| 105 | return nil, errors.New("cache version is newer") |
| 106 | } |
| 107 | // Update the timestamp so that we can detect old cache dirs. |
| 108 | err = updateTimestamp(cachedir) |
| 109 | if err != nil { |
| 110 | return nil, err |
| 111 | } |
| 112 | |
| 113 | case errors.Is(err, os.ErrNotExist): |
| 114 | // Create the repo cache dir. The parent exists, so Mkdir suffices. |
| 115 | err := os.Mkdir(cachedir, dirMode) |
| 116 | switch { |
| 117 | case err == nil: |
| 118 | created = true |
| 119 | case errors.Is(err, os.ErrExist): |
| 120 | default: |
| 121 | return nil, errors.WithStack(err) |
| 122 | } |
| 123 | |
| 124 | default: |
| 125 | return nil, errors.Wrap(err, "readVersion") |
| 126 | } |
| 127 | |
| 128 | if v < cacheVersion { |
| 129 | err = os.WriteFile(filepath.Join(cachedir, "version"), []byte(fmt.Sprintf("%d", cacheVersion)), fileMode) |
| 130 | if err != nil { |
| 131 | return nil, errors.WithStack(err) |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | for _, p := range cacheLayoutPaths { |
| 136 | if err = os.MkdirAll(filepath.Join(cachedir, p), dirMode); err != nil { |