Repository: gohugoio/hugo (language: go)

Issue:
--printPathWarnings should also warn about duplicate content paths



Discussion / hints:

Fix patch:
diff --git a/hugolib/content_map.go b/hugolib/content_map.go
index b75ccdbcb7d..452bf8efa23 100644
--- a/hugolib/content_map.go
+++ b/hugolib/content_map.go
@@ -164,6 +164,55 @@ func (cfg contentMapConfig) getTaxonomyConfig(s string) (v viewName) {
 	return
 }
 
+func (m *pageMap) insertPageWithLock(s string, p *pageState) (contentNodeI, contentNodeI, bool) {
+	u, n, replaced := m.treePages.InsertIntoValuesDimensionWithLock(s, p)
+
+	if replaced && !m.s.h.isRebuild() && m.s.conf.PrintPathWarnings {
+		var messageDetail string
+		if p1, ok := n.(*pageState); ok && p1.File() != nil {
+			messageDetail = fmt.Sprintf(" file: %q", p1.File().Filename())
+		}
+		if p2, ok := u.(*pageState); ok && p2.File() != nil {
+			messageDetail += fmt.Sprintf(" file: %q", p2.File().Filename())
+		}
+
+		m.s.Log.Warnf("Duplicate content path: %q%s", s, messageDetail)
+	}
+
+	return u, n, replaced
+}
+
+func (m *pageMap) insertResourceWithLock(s string, r contentNodeI) (contentNodeI, contentNodeI, bool) {
+	u, n, replaced := m.treeResources.InsertIntoValuesDimensionWithLock(s, r)
+	if replaced {
+		m.handleDuplicateResourcePath(s, r, n)
+	}
+	return u, n, replaced
+}
+
+func (m *pageMap) insertResource(s string, r contentNodeI) (contentNodeI, contentNodeI, bool) {
+	u, n, replaced := m.treeResources.InsertIntoValuesDimension(s, r)
+	if replaced {
+		m.handleDuplicateResourcePath(s, r, n)
+	}
+	return u, n, replaced
+}
+
+func (m *pageMap) handleDuplicateResourcePath(s string, updated, existing contentNodeI) {
+	if m.s.h.isRebuild() || !m.s.conf.PrintPathWarnings {
+		return
+	}
+	var messageDetail string
+	if r1, ok := existing.(*resourceSource); ok && r1.fi != nil {
+		messageDetail = fmt.Sprintf(" file: %q", r1.fi.Meta().Filename)
+	}
+	if r2, ok := updated.(*resourceSource); ok && r2.fi != nil {
+		messageDetail += fmt.Sprintf(" file: %q", r2.fi.Meta().Filename)
+	}
+
+	m.s.Log.Warnf("Duplicate resource path: %q%s", s, messageDetail)
+}
+
 func (m *pageMap) AddFi(fi hugofs.FileMetaInfo, buildConfig *BuildCfg) (pageCount uint64, resourceCount uint64, addErr error) {
 	if fi.IsDir() {
 		return
@@ -207,7 +256,7 @@ func (m *pageMap) AddFi(fi hugofs.FileMetaInfo, buildConfig *BuildCfg) (pageCoun
 			rs = &resourceSource{path: pi, opener: r, fi: fim, langIndex: fim.Meta().LangIndex}
 		}
 
-		tree.InsertIntoValuesDimension(key, rs)
+		_, _, _ = m.insertResource(key, rs)
 
 		return nil
 	}
@@ -261,7 +310,7 @@ func (m *pageMap) AddFi(fi hugofs.FileMetaInfo, buildConfig *BuildCfg) (pageCoun
 			return
 		}
 
-		m.treePages.InsertIntoValuesDimensionWithLock(pi.Base(), p)
+		m.insertPageWithLock(pi.Base(), p)
 
 	}
 	return
@@ -336,7 +385,7 @@ func (m *pageMap) addPagesFromGoTmplFi(fi hugofs.FileMetaInfo, buildConfig *Buil
 						return nil
 					}
 
-					u, n, replaced := s.pageMap.treePages.InsertIntoValuesDimensionWithLock(pi.Base(), ps)
+					u, n, replaced := s.pageMap.insertPageWithLock(pi.Base(), ps)
 
 					if h.isRebuild() {
 						if replaced {
@@ -358,9 +407,9 @@ func (m *pageMap) addPagesFromGoTmplFi(fi hugofs.FileMetaInfo, buildConfig *Buil
 						return err
 					}
 
-					rs := &resourceSource{path: rc.PathInfo, rc: rc, opener: nil, fi: nil, langIndex: s.languagei}
+					rs := &resourceSource{path: rc.PathInfo, rc: rc, opener: nil, fi: pt.GoTmplFi, langIndex: s.languagei}
 
-					_, n, replaced := s.pageMap.treeResources.InsertIntoValuesDimensionWithLock(rc.PathInfo.Base(), rs)
+					_, n, replaced := s.pageMap.insertResourceWithLock(rc.PathInfo.Base(), rs)
 
 					if h.isRebuild() && replaced {
 						pt.AddChange(n.GetIdentity())


Test patch:
diff --git a/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go b/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
index 75283a1229c..7f0f19f1c93 100644
--- a/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
+++ b/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
@@ -518,3 +518,70 @@ disableKinds = ['home','section','rss','sitemap','taxonomy','term']
 		"data1.yaml|param1v",
 	)
 }
+
+func TestPagesFromGoTmplPathWarningsPathPage(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableKinds = ['home','section','rss','sitemap','taxonomy','term']
+printPathWarnings = true
+-- content/_content.gotmpl --
+{{ .AddPage (dict "path" "p1" "title" "p1" ) }}
+{{ .AddPage (dict "path" "p2" "title" "p2" ) }}
+-- content/p1.md --
+---
+title: "p1"
+---
+-- layouts/_default/single.html --
+{{ .Title }}|
+`
+
+	b := hugolib.Test(t, files, hugolib.TestOptWarn())
+
+	b.AssertFileContent("public/p1/index.html", "p1|")
+
+	b.AssertLogContains("Duplicate content path")
+
+	files = strings.ReplaceAll(files, `"path" "p1"`, `"path" "p1new"`)
+
+	b = hugolib.Test(t, files, hugolib.TestOptWarn())
+
+	b.AssertLogNotContains("WARN")
+}
+
+func TestPagesFromGoTmplPathWarningsPathResource(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableKinds = ['home','section','rss','sitemap','taxonomy','term']
+printPathWarnings = true
+-- content/_content.gotmpl --
+{{ .AddResource (dict "path" "p1/data1.yaml" "content" (dict "value" "data1" ) ) }}
+{{ .AddResource (dict "path" "p1/data2.yaml" "content" (dict "value" "data2" ) ) }}
+
+-- content/p1/index.md --
+---
+title: "p1"
+---
+-- content/p1/data1.yaml --
+value: data1
+-- layouts/_default/single.html --
+{{ .Title }}|
+`
+
+	b := hugolib.Test(t, files, hugolib.TestOptWarn())
+
+	b.AssertFileContent("public/p1/index.html", "p1|")
+
+	b.AssertLogContains("Duplicate resource path")
+
+	files = strings.ReplaceAll(files, `"path" "p1/data1.yaml"`, `"path" "p1/data1new.yaml"`)
+
+	b = hugolib.Test(t, files, hugolib.TestOptWarn())
+
+	b.AssertLogNotContains("WARN")
+}