shithub: hugo

Download patch

ref: 33502667fbacf57167ede66df8f13e308a4a9aec
parent: d3489eba5dfc0ecdc032016d9db0746213dd5f0e
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Nov 14 06:53:45 EST 2018

cache/filecache: Add a filecache root dir

This is just a safe guard to make sure we don't evict/remove files that do not belong to the cache.

--- a/cache/filecache/filecache.go
+++ b/cache/filecache/filecache.go
@@ -31,6 +31,10 @@
 	"github.com/spf13/afero"
 )
 
+const (
+	filecacheRootDirname = "filecache"
+)
+
 // Cache caches a set of files in a directory. This is usually a file on
 // disk, but since this is backed by an Afero file system, it can be anything.
 type Cache struct {
@@ -276,11 +280,24 @@
 		return nil, err
 	}
 
+	genDir := filepath.FromSlash("/_gen")
+
 	fs := p.Fs.Source
 
 	m := make(Caches)
 	for k, v := range dcfg {
-		baseDir := filepath.Join(v.Dir, k)
+		var baseDir string
+		if !strings.Contains(v.Dir, genDir) {
+			// We do cache eviction (file removes) and since the user can set
+			// his/hers own cache directory, we really want to make sure
+			// we do not delete any files that do not belong to this cache.
+			// We do add the cache name as the root, but this is an extra safe
+			// guard. We skip the files inside /resources/_gen/ because
+			// that would be breaking.
+			baseDir = filepath.Join(v.Dir, filecacheRootDirname, k)
+		} else {
+			baseDir = filepath.Join(v.Dir, k)
+		}
 		if err = fs.MkdirAll(baseDir, 0777); err != nil {
 			return nil, err
 		}
--- a/cache/filecache/filecache_config.go
+++ b/cache/filecache/filecache_config.go
@@ -157,6 +157,10 @@
 			return c, errors.Errorf("%q must either start with a placeholder (e.g. :cacheDir, :resourceDir) or be absolute", v.Dir)
 		}
 
+		if len(v.Dir) < 5 {
+			return c, errors.Errorf("%q is not a valid cache dir", v.Dir)
+		}
+
 		if disabled {
 			v.MaxAge = 0
 		}
--- a/cache/filecache/filecache_config_test.go
+++ b/cache/filecache/filecache_config_test.go
@@ -33,6 +33,7 @@
 	assert := require.New(t)
 
 	configStr := `
+resourceDir = "myresources"
 [caches]
 [caches.getJSON]
 maxAge = "10m"
@@ -72,6 +73,7 @@
 	assert := require.New(t)
 
 	configStr := `
+resourceDir = "myresources"
 ignoreCache = true
 [caches]
 [caches.getJSON]
--- a/cache/filecache/filecache_test.go
+++ b/cache/filecache/filecache_test.go
@@ -41,6 +41,8 @@
 	for _, cacheDir := range []string{"mycache", ""} {
 
 		configStr := `
+workingDir = "/my/work"
+resourceDir = "resources"
 cacheDir = "CACHEDIR"
 [caches]
 [caches.getJSON]
@@ -69,12 +71,20 @@
 		filename, err := bfs.RealPath("key")
 		assert.NoError(err)
 		if cacheDir != "" {
-			assert.Equal(filepath.FromSlash(cacheDir+"/c/getjson/key"), filename)
+			assert.Equal(filepath.FromSlash(cacheDir+"/c/"+filecacheRootDirname+"/getjson/key"), filename)
 		} else {
 			// Temp dir.
-			assert.Regexp(regexp.MustCompile("hugo_cache.*key"), filename)
+			assert.Regexp(regexp.MustCompile(".*hugo_cache.*"+filecacheRootDirname+".*key"), filename)
 		}
 
+		c = caches.Get("images")
+		assert.NotNil(c)
+		assert.Equal(time.Duration(-1), c.maxAge)
+		bfs, ok = c.Fs.(*afero.BasePathFs)
+		assert.True(ok)
+		filename, _ = bfs.RealPath("key")
+		assert.Equal(filepath.FromSlash("/my/work/resources/_gen/images/key"), filename)
+
 		rf := func(s string) func() (io.ReadCloser, error) {
 			return func() (io.ReadCloser, error) {
 				return struct {
@@ -149,6 +159,7 @@
 	assert := require.New(t)
 
 	configStr := `
+resourceDir = "myresources"
 [caches]
 [caches.getjson]
 maxAge = "1s"
--- a/tpl/data/resources_test.go
+++ b/tpl/data/resources_test.go
@@ -180,6 +180,7 @@
 }
 
 func newDeps(cfg config.Provider) *deps.Deps {
+	cfg.Set("resourceDir", "resources")
 	l := langs.NewLanguage("en", cfg)
 	l.Set("i18nDir", "i18n")
 	cs, err := helpers.NewContentSpec(l)