ref: 77cbe4d60bfa708cbf695ae5f2524d4f76007e71
parent: c507e2717df7dd4b870478033bc5ece0b039a8c4
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
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) {--
⑨