tplimpl: Refactor imageConfig into a struct

Updates #2701
This commit is contained in:
Bjørn Erik Pedersen
2017-02-17 14:22:40 +01:00
parent c507e2717d
commit 77cbe4d60b
3 changed files with 34 additions and 79 deletions

View File

@@ -40,6 +40,8 @@ import (
"time"
"unicode/utf8"
"github.com/spf13/hugo/hugofs"
"github.com/bep/inflect"
"github.com/spf13/afero"
"github.com/spf13/cast"
@@ -57,6 +59,7 @@ import (
type templateFuncster struct {
funcMap template.FuncMap
cachedPartials partialCache
image *imageHandler
*deps.Deps
}
@@ -64,6 +67,7 @@ func newTemplateFuncster(deps *deps.Deps) *templateFuncster {
return &templateFuncster{
Deps: deps,
cachedPartials: partialCache{p: make(map[string]template.HTML)},
image: &imageHandler{fs: deps.Fs, imageConfigCache: map[string]image.Config{}},
}
}
@@ -395,64 +399,43 @@ func intersect(l1, l2 interface{}) (interface{}, error) {
}
}
// 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
}
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{}
fs *hugofs.Fs
}
// 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
}
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
}
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 @@ func (t *templateFuncster) initFuncMap() {
"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) },