ref: 5ef52294f90c51697bd3f918b3c3ed83baff657a
parent: 37fb2d43e5d3ecfd1f16324556d85e202fadcc73
author: Bjørn Erik Pedersen <[email protected]>
date: Mon Apr 11 07:49:02 EDT 2016
Add Node.ID Fixes #2071
--- a/hugolib/node.go
+++ b/hugolib/node.go
@@ -14,10 +14,12 @@
package hugolib
import (
- "github.com/spf13/cast"
"html/template"
"sync"
+ "sync/atomic"
"time"
+
+ "github.com/spf13/cast"
)
type Node struct {
@@ -37,6 +39,24 @@
paginator *Pager
paginatorInit sync.Once
scratch *Scratch
+ id int
+ idInit sync.Once
+}
+
+// This should probably be owned by Site and new ids assigned on creation,
+// but that would lead to massive changes; do it simple for now.
+var nodeIDCounter uint64
+
+func nextNodeID() int {
+ return int(atomic.AddUint64(&nodeIDCounter, 1))
+}
+
+// ID returns an integer that identifies this Node.
+// This is unique for a given Hugo build, but must not be considered stable.
+// See UniqueID on Page for an identify that is stable for repeated builds.
+func (n *Node) ID() int {
+ n.idInit.Do(func() { n.id = nextNodeID() })
+ return n.id
}
func (n *Node) Now() time.Time {
--- a/hugolib/node_test.go
+++ b/hugolib/node_test.go
@@ -14,8 +14,11 @@
package hugolib
import (
+ "sync"
"testing"
"time"
+
+ "github.com/stretchr/testify/assert"
)
func TestNodeSimpleMethods(t *testing.T) {
@@ -37,4 +40,29 @@
t.Errorf("[%d] Node method error", i)
}
}
+}
+
+func TestNodeID(t *testing.T) {
+ t.Parallel()
+
+ n1 := &Node{}
+ n2 := &Node{}
+
+ assert.True(t, n1.ID() > 0)
+ assert.Equal(t, n1.ID(), n1.ID())
+ assert.True(t, n2.ID() > n1.ID())
+
+ var wg sync.WaitGroup
+
+ for i := 1; i <= 10; i++ {
+ wg.Add(1)
+ go func(j int) {
+ for k := 0; k < 10; k++ {
+ n := &Node{}
+ assert.True(t, n.ID() > 0)
+ }
+ wg.Done()
+ }(i)
+ }
+ wg.Wait()
}