shithub: hugo

Download patch

ref: 6b6dcb44a014699c289bf32fe57d4c4216777be0
parent: d96f2a460f58e91d8f6253a489d4879acfec6916
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Jul 11 15:23:22 EDT 2018

Flush partialCached cache on rebuilds

Fixes #4931

--- a/deps/deps.go
+++ b/deps/deps.go
@@ -1,6 +1,7 @@
 package deps
 
 import (
+	"sync"
 	"time"
 
 	"github.com/gohugoio/hugo/common/loggers"
@@ -22,6 +23,7 @@
 // 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,8 +71,32 @@
 
 	// 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.
 type ResourceProvider interface {
 	Update(deps *Deps) error
@@ -168,6 +194,7 @@
 		ResourceSpec:        resourceSpec,
 		Cfg:                 cfg.Language,
 		Language:            cfg.Language,
+		BuildStartListeners: &Listeners{},
 		Timeout:             time.Duration(timeoutms) * time.Millisecond,
 	}
 
@@ -209,6 +236,8 @@
 	if err := d.templateProvider.Clone(&d); err != nil {
 		return nil, err
 	}
+
+	d.BuildStartListeners = &Listeners{}
 
 	return &d, nil
 
--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -28,6 +28,7 @@
 // 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()
 	}
@@ -40,6 +41,10 @@
 	if conf.whatChanged == nil {
 		// Assume everything has changed
 		conf.whatChanged = &whatChanged{source: true, other: true}
+	}
+
+	for _, s := range h.Sites {
+		s.Deps.BuildStartListeners.Notify()
 	}
 
 	if len(events) > 0 {
--- a/tpl/partials/init_test.go
+++ b/tpl/partials/init_test.go
@@ -26,7 +26,9 @@
 	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
--- a/tpl/partials/partials.go
+++ b/tpl/partials/partials.go
@@ -34,11 +34,23 @@
 	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,
 	}
 }
 
@@ -45,7 +57,7 @@
 // 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,