Flush partialCached cache on rebuilds
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 11 Jul 2018 17:23:22 +0000 (19:23 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 11 Jul 2018 18:40:04 +0000 (20:40 +0200)
Fixes #4931

deps/deps.go
hugolib/hugo_sites_build.go
tpl/partials/init_test.go
tpl/partials/partials.go

index b32c7e2e9897e0b0f9c717facc7980b747367002..5a97ec7f2c59d6b16fcbe50fba1d11b222cbda50 100644 (file)
@@ -1,6 +1,7 @@
 package deps
 
 import (
+       "sync"
        "time"
 
        "github.com/gohugoio/hugo/common/loggers"
@@ -22,6 +23,7 @@ import (
 // There will be normally only one instance of deps in play
 // at a given time, i.e. one per Site built.
 type Deps struct {
+
        // The logger to use.
        Log *jww.Notepad `json:"-"`
 
@@ -69,6 +71,30 @@ type Deps struct {
 
        // Timeout is configurable in site config.
        Timeout time.Duration
+
+       // BuildStartListeners will be notified before a build starts.
+       BuildStartListeners *Listeners
+}
+
+type Listeners struct {
+       sync.Mutex
+
+       // A list of funcs to be notified about an event.
+       listeners []func()
+}
+
+func (b *Listeners) Add(f func()) {
+       b.Lock()
+       defer b.Unlock()
+       b.listeners = append(b.listeners, f)
+}
+
+func (b *Listeners) Notify() {
+       b.Lock()
+       defer b.Unlock()
+       for _, notify := range b.listeners {
+               notify()
+       }
 }
 
 // ResourceProvider is used to create and refresh, and clone resources needed.
@@ -168,6 +194,7 @@ func New(cfg DepsCfg) (*Deps, error) {
                ResourceSpec:        resourceSpec,
                Cfg:                 cfg.Language,
                Language:            cfg.Language,
+               BuildStartListeners: &Listeners{},
                Timeout:             time.Duration(timeoutms) * time.Millisecond,
        }
 
@@ -210,6 +237,8 @@ func (d Deps) ForLanguage(cfg DepsCfg) (*Deps, error) {
                return nil, err
        }
 
+       d.BuildStartListeners = &Listeners{}
+
        return &d, nil
 
 }
index 7769b68dc6bb705f68f3b80ddee05b60c379ebe7..8ca2128a166f33b0e03912fa66c87cc15481bbb5 100644 (file)
@@ -28,6 +28,7 @@ import (
 // Build builds all sites. If filesystem events are provided,
 // this is considered to be a potential partial rebuild.
 func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
+
        if h.Metrics != nil {
                h.Metrics.Reset()
        }
@@ -42,6 +43,10 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
                conf.whatChanged = &whatChanged{source: true, other: true}
        }
 
+       for _, s := range h.Sites {
+               s.Deps.BuildStartListeners.Notify()
+       }
+
        if len(events) > 0 {
                // Rebuild
                if err := h.initRebuild(conf); err != nil {
index ef284a8269254469cc248faa8196341c17063e12..4832e6b66bcb75ea5779dd970563c6828b30f19c 100644 (file)
@@ -26,7 +26,9 @@ func TestInit(t *testing.T) {
        var ns *internal.TemplateFuncsNamespace
 
        for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
-               ns = nsf(&deps.Deps{})
+               ns = nsf(&deps.Deps{
+                       BuildStartListeners: &deps.Listeners{},
+               })
                if ns.Name == name {
                        found = true
                        break
index 18b8d7ed62ea6f221b96f03d60d1c73bae8dfe21..266329721403d53e49599b1a27de89aa975650dc 100644 (file)
@@ -34,18 +34,30 @@ type partialCache struct {
        p map[string]interface{}
 }
 
+func (p *partialCache) clear() {
+       p.Lock()
+       defer p.Unlock()
+       p.p = make(map[string]interface{})
+}
+
 // New returns a new instance of the templates-namespaced template functions.
 func New(deps *deps.Deps) *Namespace {
+       cache := &partialCache{p: make(map[string]interface{})}
+       deps.BuildStartListeners.Add(
+               func() {
+                       cache.clear()
+               })
+
        return &Namespace{
                deps:           deps,
-               cachedPartials: partialCache{p: make(map[string]interface{})},
+               cachedPartials: cache,
        }
 }
 
 // Namespace provides template functions for the "templates" namespace.
 type Namespace struct {
        deps           *deps.Deps
-       cachedPartials partialCache
+       cachedPartials *partialCache
 }
 
 // Include executes the named partial and returns either a string,