aboutsummaryrefslogtreecommitdiffhomepage
path: root/cache/filecache/filecache_pruner.go
diff options
context:
space:
mode:
Diffstat (limited to 'cache/filecache/filecache_pruner.go')
-rw-r--r--cache/filecache/filecache_pruner.go117
1 files changed, 82 insertions, 35 deletions
diff --git a/cache/filecache/filecache_pruner.go b/cache/filecache/filecache_pruner.go
index 322eabf92..c6fd4497e 100644
--- a/cache/filecache/filecache_pruner.go
+++ b/cache/filecache/filecache_pruner.go
@@ -28,53 +28,100 @@ import (
func (c Caches) Prune() (int, error) {
counter := 0
for k, cache := range c {
- err := afero.Walk(cache.Fs, "", func(name string, info os.FileInfo, err error) error {
- if info == nil {
- return nil
- }
- name = cleanID(name)
-
- if info.IsDir() {
- f, err := cache.Fs.Open(name)
- if err != nil {
- // This cache dir may not exist.
- return nil
- }
- defer f.Close()
- _, err = f.Readdirnames(1)
- if err == io.EOF {
- // Empty dir.
- return cache.Fs.Remove(name)
- }
+ count, err := cache.Prune(false)
+
+ if err != nil {
+ return counter, errors.Wrapf(err, "failed to prune cache %q", k)
+ }
+
+ counter += count
+
+ }
+
+ return counter, nil
+}
+
+// Prune removes expired and unused items from this cache.
+// If force is set, everything will be removed not considering expiry time.
+func (c *Cache) Prune(force bool) (int, error) {
+ if c.pruneAllRootDir != "" {
+ return c.pruneRootDir(force)
+ }
+
+ counter := 0
+
+ err := afero.Walk(c.Fs, "", func(name string, info os.FileInfo, err error) error {
+ if info == nil {
+ return nil
+ }
+
+ name = cleanID(name)
+ if info.IsDir() {
+ f, err := c.Fs.Open(name)
+ if err != nil {
+ // This cache dir may not exist.
return nil
}
+ defer f.Close()
+ _, err = f.Readdirnames(1)
+ if err == io.EOF {
+ // Empty dir.
+ return c.Fs.Remove(name)
+ }
+
+ return nil
+ }
- shouldRemove := cache.isExpired(info.ModTime())
+ shouldRemove := force || c.isExpired(info.ModTime())
- if !shouldRemove && len(cache.nlocker.seen) > 0 {
- // Remove it if it's not been touched/used in the last build.
- _, seen := cache.nlocker.seen[name]
- shouldRemove = !seen
- }
+ if !shouldRemove && len(c.nlocker.seen) > 0 {
+ // Remove it if it's not been touched/used in the last build.
+ _, seen := c.nlocker.seen[name]
+ shouldRemove = !seen
+ }
- if shouldRemove {
- err := cache.Fs.Remove(name)
- if err == nil {
- counter++
- }
- return err
+ if shouldRemove {
+ err := c.Fs.Remove(name)
+ if err == nil {
+ counter++
}
+ return err
+ }
- return nil
- })
+ return nil
+ })
- if err != nil {
- return counter, errors.Wrapf(err, "failed to prune cache %q", k)
+ return counter, err
+}
+
+func (c *Cache) pruneRootDir(force bool) (int, error) {
+
+ info, err := c.Fs.Stat(c.pruneAllRootDir)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return 0, nil
}
+ return 0, err
+ }
+ if !force && !c.isExpired(info.ModTime()) {
+ return 0, nil
}
- return counter, nil
+ counter := 0
+ // Module cache has 0555 directories; make them writable in order to remove content.
+ afero.Walk(c.Fs, c.pruneAllRootDir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return nil
+ }
+ if info.IsDir() {
+ counter++
+ c.Fs.Chmod(path, 0777)
+ }
+ return nil
+ })
+ return 1, c.Fs.RemoveAll(c.pruneAllRootDir)
+
}