diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-11-14 14:06:46 +0300 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-11-15 01:14:51 +0300 |
commit | 3c29c5af8ee865ef20741f576088e031e940c3d2 (patch) | |
tree | 4e05740a9e4f99360aa843da2a4d82d943c825b1 /cache/filecache/filecache_pruner.go | |
parent | 33502667fbacf57167ede66df8f13e308a4a9aec (diff) |
cache/filecache: Add a cache prune func
Fixes #5439
Diffstat (limited to 'cache/filecache/filecache_pruner.go')
-rw-r--r-- | cache/filecache/filecache_pruner.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/cache/filecache/filecache_pruner.go b/cache/filecache/filecache_pruner.go new file mode 100644 index 000000000..322eabf92 --- /dev/null +++ b/cache/filecache/filecache_pruner.go @@ -0,0 +1,80 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package filecache + +import ( + "io" + "os" + + "github.com/pkg/errors" + "github.com/spf13/afero" +) + +// Prune removes expired and unused items from this cache. +// The last one requires a full build so the cache usage can be tracked. +// Note that we operate directly on the filesystem here, so this is not +// thread safe. +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) + } + + return nil + } + + shouldRemove := cache.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 { + err := cache.Fs.Remove(name) + if err == nil { + counter++ + } + return err + } + + return nil + }) + + if err != nil { + return counter, errors.Wrapf(err, "failed to prune cache %q", k) + } + + } + + return counter, nil +} |