Merge pull request #1436 from restic/remove-old-cache

Remove old cache directories
This commit is contained in:
Alexander Neumann
2017-11-27 21:37:05 +01:00
7 changed files with 136 additions and 25 deletions

View File

@@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"strconv"
"time"
"github.com/pkg/errors"
"github.com/restic/restic/internal/debug"
@@ -84,10 +85,12 @@ func writeCachedirTag(dir string) error {
// performReadahead returns true.
func New(id string, basedir string) (c *Cache, err error) {
if basedir == "" {
basedir, err = defaultCacheDir()
if err != nil {
return nil, err
}
basedir, err = DefaultDir()
}
err = mkdirCacheDir(basedir)
if err != nil {
return nil, err
}
// create base dir and tag it as a cache directory
@@ -112,6 +115,12 @@ func New(id string, basedir string) (c *Cache, err error) {
return nil, err
}
// update the timestamp so that we can detect old cache dirs
err = updateTimestamp(cachedir)
if err != nil {
return nil, err
}
if v < cacheVersion {
err = ioutil.WriteFile(filepath.Join(cachedir, "version"), []byte(fmt.Sprintf("%d", cacheVersion)), 0644)
if err != nil {
@@ -137,6 +146,53 @@ func New(id string, basedir string) (c *Cache, err error) {
return c, nil
}
// updateTimestamp sets the modification timestamp (mtime and atime) for the
// directory d to the current time.
func updateTimestamp(d string) error {
t := time.Now()
return fs.Chtimes(d, t, t)
}
const maxCacheAge = 30 * 24 * time.Hour
// Old returns a list of cache directories with a modification time of more
// than 30 days ago.
func Old(basedir string) ([]string, error) {
var oldCacheDirs []string
f, err := fs.Open(basedir)
if err != nil {
return nil, err
}
entries, err := f.Readdir(-1)
if err != nil {
return nil, err
}
oldest := time.Now().Add(-maxCacheAge)
for _, fi := range entries {
if !fi.IsDir() {
continue
}
if !fi.ModTime().Before(oldest) {
continue
}
oldCacheDirs = append(oldCacheDirs, fi.Name())
}
err = f.Close()
if err != nil {
return nil, err
}
debug.Log("%d old cache dirs found", len(oldCacheDirs))
return oldCacheDirs, nil
}
// errNoSuchFile is returned when a file is not cached.
type errNoSuchFile struct {
Type string

26
internal/cache/dir.go vendored
View File

@@ -49,29 +49,25 @@ func darwinCacheDir() (string, error) {
return filepath.Join(home, "Library", "Caches", "restic"), nil
}
// defaultCacheDir determines and creates the default cache directory for this
// system.
func defaultCacheDir() (string, error) {
var cachedir string
var err error
// DefaultDir returns the default cache directory for the current OS.
func DefaultDir() (cachedir string, err error) {
switch runtime.GOOS {
case "darwin":
cachedir, err = darwinCacheDir()
case "windows":
cachedir, err = windowsCacheDir()
default:
// Default to XDG for Linux and any other OSes.
cachedir, err = xdgCacheDir()
}
if err != nil {
return "", err
}
// Default to XDG for Linux and any other OSes.
return xdgCacheDir()
}
func mkdirCacheDir(cachedir string) error {
fi, err := fs.Stat(cachedir)
if os.IsNotExist(errors.Cause(err)) {
err = fs.MkdirAll(cachedir, 0700)
if err != nil {
return "", errors.Wrap(err, "MkdirAll")
return errors.Wrap(err, "MkdirAll")
}
fi, err = fs.Stat(cachedir)
@@ -79,12 +75,12 @@ func defaultCacheDir() (string, error) {
}
if err != nil {
return "", errors.Wrap(err, "Stat")
return errors.Wrap(err, "Stat")
}
if !fi.IsDir() {
return "", errors.Errorf("cache dir %v is not a directory", cachedir)
return errors.Errorf("cache dir %v is not a directory", cachedir)
}
return cachedir, nil
return nil
}

View File

@@ -4,6 +4,7 @@ import (
"io"
"os"
"path/filepath"
"time"
)
// File is an open file on a file system.
@@ -120,3 +121,12 @@ func RemoveIfExists(filename string) error {
}
return err
}
// Chtimes changes the access and modification times of the named file,
// similar to the Unix utime() or utimes() functions.
//
// The underlying filesystem may truncate or round the values to a less
// precise time unit. If there is an error, it will be of type *PathError.
func Chtimes(name string, atime time.Time, mtime time.Time) error {
return os.Chtimes(fixpath(name), atime, mtime)
}