shithub: hugo

Download patch

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()
 }