ref: 77cbe4d60bfa708cbf695ae5f2524d4f76007e71
parent: c507e2717df7dd4b870478033bc5ece0b039a8c4
author: Bjørn Erik Pedersen <[email protected]>
date: Fri Feb 17 09:22:40 EST 2017
tplimpl: Refactor imageConfig into a struct Updates #2701
--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -190,8 +190,6 @@
for i, s := range h.Sites {
h.Sites[i] = s.reset()
}
-
- tplimpl.ResetCaches()
}
func (h *HugoSites) createSitesFromConfig() error {
--- a/tpl/tplimpl/template_funcs.go
+++ b/tpl/tplimpl/template_funcs.go
@@ -40,6 +40,8 @@
"time"
"unicode/utf8"
+ "github.com/spf13/hugo/hugofs"
+
"github.com/bep/inflect"
"github.com/spf13/afero"
"github.com/spf13/cast"
@@ -57,6 +59,7 @@
type templateFuncster struct {
funcMap template.FuncMap
cachedPartials partialCache
+ image *imageHandler
*deps.Deps
}
@@ -64,6 +67,7 @@
return &templateFuncster{
Deps: deps,
cachedPartials: partialCache{p: make(map[string]template.HTML)},
+ image: &imageHandler{fs: deps.Fs, imageConfigCache: map[string]image.Config{}},
}
}
@@ -395,36 +399,15 @@
}
}
-// ResetCaches resets all caches that might be used during build.
-// TODO(bep) globals move image config cache to funcster
-func ResetCaches() {
- resetImageConfigCache()
-}
-
-// imageConfigCache is a lockable cache for image.Config objects. It must be
-// locked before reading or writing to config.
-type imageConfigCache struct {
- config map[string]image.Config
+type imageHandler struct {
+ imageConfigCache map[string]image.Config
sync.RWMutex
+ fs *hugofs.Fs
}
-var defaultImageConfigCache = imageConfigCache{
- config: map[string]image.Config{},
-}
-
-// resetImageConfigCache initializes and resets the imageConfig cache for the
-// imageConfig template function. This should be run once before every batch of
-// template renderers so the cache is cleared for new data.
-func resetImageConfigCache() {
- defaultImageConfigCache.Lock()
- defer defaultImageConfigCache.Unlock()
-
- defaultImageConfigCache.config = map[string]image.Config{}
-}
-
// imageConfig returns the image.Config for the specified path relative to the
-// working directory. resetImageConfigCache must be run beforehand.
-func (t *templateFuncster) imageConfig(path interface{}) (image.Config, error) {
+// working directory.
+func (ic *imageHandler) config(path interface{}) (image.Config, error) {
filename, err := cast.ToStringE(path)
if err != nil {
return image.Config{}, err
@@ -431,19 +414,19 @@
}
if filename == "" {
- return image.Config{}, errors.New("imageConfig needs a filename")
+ return image.Config{}, errors.New("config needs a filename")
}
// Check cache for image config.
- defaultImageConfigCache.RLock()
- config, ok := defaultImageConfigCache.config[filename]
- defaultImageConfigCache.RUnlock()
+ ic.RLock()
+ config, ok := ic.imageConfigCache[filename]
+ ic.RUnlock()
if ok {
return config, nil
}
- f, err := t.Fs.WorkingDir.Open(filename)
+ f, err := ic.fs.WorkingDir.Open(filename)
if err != nil {
return image.Config{}, err
}
@@ -450,9 +433,9 @@
config, _, err = image.DecodeConfig(f)
- defaultImageConfigCache.Lock()
- defaultImageConfigCache.config[filename] = config
- defaultImageConfigCache.Unlock()
+ ic.Lock()
+ ic.imageConfigCache[filename] = config
+ ic.Unlock()
return config, err
}
@@ -2144,7 +2127,7 @@
"htmlEscape": htmlEscape,
"htmlUnescape": htmlUnescape,
"humanize": humanize,
- "imageConfig": t.imageConfig,
+ "imageConfig": t.image.config,
"in": in,
"index": index,
"int": func(v interface{}) (int, error) { return cast.ToIntE(v) },
--- a/tpl/tplimpl/template_funcs_test.go
+++ b/tpl/tplimpl/template_funcs_test.go
@@ -667,16 +667,13 @@
f := newTestFuncsterWithViper(v)
for i, this := range []struct {
- resetCache bool
- path string
- input []byte
- expected image.Config
+ path string
+ input []byte
+ expected image.Config
}{
- // Make sure that the cache is initialized by default.
{
- resetCache: false,
- path: "a.png",
- input: blankImage(10, 10),
+ path: "a.png",
+ input: blankImage(10, 10),
expected: image.Config{
Width: 10,
Height: 10,
@@ -684,9 +681,8 @@
},
},
{
- resetCache: true,
- path: "a.png",
- input: blankImage(10, 10),
+ path: "a.png",
+ input: blankImage(10, 10),
expected: image.Config{
Width: 10,
Height: 10,
@@ -694,9 +690,8 @@
},
},
{
- resetCache: false,
- path: "b.png",
- input: blankImage(20, 15),
+ path: "b.png",
+ input: blankImage(20, 15),
expected: image.Config{
Width: 20,
Height: 15,
@@ -704,9 +699,8 @@
},
},
{
- resetCache: false,
- path: "a.png",
- input: blankImage(20, 15),
+ path: "a.png",
+ input: blankImage(20, 15),
expected: image.Config{
Width: 10,
Height: 10,
@@ -713,24 +707,10 @@
ColorModel: color.NRGBAModel,
},
},
- {
- resetCache: true,
- path: "a.png",
- input: blankImage(20, 15),
- expected: image.Config{
- Width: 20,
- Height: 15,
- ColorModel: color.NRGBAModel,
- },
- },
} {
afero.WriteFile(f.Fs.Source, filepath.Join(workingDir, this.path), this.input, 0755)
- if this.resetCache {
- resetImageConfigCache()
- }
-
- result, err := f.imageConfig(this.path)
+ result, err := f.image.config(this.path)
if err != nil {
t.Errorf("imageConfig returned error: %s", err)
}
@@ -739,29 +719,23 @@
t.Errorf("[%d] imageConfig: expected '%v', got '%v'", i, this.expected, result)
}
- if len(defaultImageConfigCache.config) == 0 {
+ if len(f.image.imageConfigCache) == 0 {
t.Error("defaultImageConfigCache should have at least 1 item")
}
}
- if _, err := f.imageConfig(t); err == nil {
+ if _, err := f.image.config(t); err == nil {
t.Error("Expected error from imageConfig when passed invalid path")
}
- if _, err := f.imageConfig("non-existent.png"); err == nil {
+ if _, err := f.image.config("non-existent.png"); err == nil {
t.Error("Expected error from imageConfig when passed non-existent file")
}
- if _, err := f.imageConfig(""); err == nil {
+ if _, err := f.image.config(""); err == nil {
t.Error("Expected error from imageConfig when passed empty path")
}
- // test cache clearing
- ResetCaches()
-
- if len(defaultImageConfigCache.config) != 0 {
- t.Error("ResetCaches should have cleared defaultImageConfigCache")
- }
}
func TestIn(t *testing.T) {