Repository: gohugoio/hugo (language: go)

Issue:
Bundled resource pages (e.g. md file) not refreshed on server rebuilds
Example site [here](https://github.com/TiGR/hugo-testing/tree/md-caching-issue). Run it in `hugo server` mode. Then, open `/test/` page. Now, edit `content/test/doc.md` file. Notice in the terminal that hugo notices change, runs rebuild, but still render the old content.

It seems to be related to markdown files only, as other files do reload fine.

### What version of Hugo are you using (`hugo version`)?

<pre>
$ hugo version
hugo v0.123.0-DEV+extended linux/amd64 BuildDate=unknown
</pre>

### Does this issue reproduce with the latest release?

No, hugo 0.122 and before it works fine.


Discussion / hints:
Thanks, I guess I didn't test that. On a note related to the issue of duplication; it strikes me as a little bit odd that you have `index.html` as the main bundle page, but have `md` files bundles, but you probably have a good reason.
Well, as a site with a lot of legacy content we have it in all possible ways: with `index.html` and `doc.html`, with `index.html` and `doc.md`, with `index.md` and `doc.md`, and with `index.md` and `doc.html`.

It actually doesn't matter, as the issue appears with both `index.html` and `index.md`.

Fix patch:
diff --git a/common/paths/pathparser.go b/common/paths/pathparser.go
index f506eb60fbc..eceb46b3d58 100644
--- a/common/paths/pathparser.go
+++ b/common/paths/pathparser.go
@@ -480,6 +480,11 @@ func (p *Path) IsLeafBundle() bool {
 	return p.bundleType == PathTypeLeaf
 }
 
+func (p Path) ForBundleType(t PathType) *Path {
+	p.bundleType = t
+	return &p
+}
+
 func (p *Path) identifierAsString(i int) string {
 	i = p.identifierIndex(i)
 	if i == -1 {
diff --git a/hugolib/content_map_page.go b/hugolib/content_map_page.go
index 75863acbd8a..43c67ce738a 100644
--- a/hugolib/content_map_page.go
+++ b/hugolib/content_map_page.go
@@ -127,7 +127,22 @@ type pageTrees struct {
 
 // collectIdentities collects all identities from in all trees matching the given key.
 // This will at most match in one tree, but may give identies from multiple dimensions (e.g. language).
-func (t *pageTrees) collectIdentities(key string) []identity.Identity {
+func (t *pageTrees) collectIdentities(p *paths.Path) []identity.Identity {
+	ids := t.collectIdentitiesFor(p.Base())
+
+	if p.Component() == files.ComponentFolderContent {
+		// It may also be a bundled content resource.
+		if n := t.treeResources.Get(p.ForBundleType(paths.PathTypeContentResource).Base()); n != nil {
+			n.ForEeachIdentity(func(id identity.Identity) bool {
+				ids = append(ids, id)
+				return false
+			})
+		}
+	}
+	return ids
+}
+
+func (t *pageTrees) collectIdentitiesFor(key string) []identity.Identity {
 	var ids []identity.Identity
 	if n := t.treePages.Get(key); n != nil {
 		n.ForEeachIdentity(func(id identity.Identity) bool {
@@ -135,6 +150,7 @@ func (t *pageTrees) collectIdentities(key string) []identity.Identity {
 			return false
 		})
 	}
+
 	if n := t.treeResources.Get(key); n != nil {
 		n.ForEeachIdentity(func(id identity.Identity) bool {
 			ids = append(ids, id)
diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go
index 4b22c19563c..17af2d8d8dc 100644
--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -702,9 +702,7 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
 		switch pathInfo.Component() {
 		case files.ComponentFolderContent:
 			logger.Println("Source changed", pathInfo.Path())
-			base := pathInfo.Base()
-
-			if ids := h.pageTrees.collectIdentities(base); len(ids) > 0 {
+			if ids := h.pageTrees.collectIdentities(pathInfo); len(ids) > 0 {
 				changes = append(changes, ids...)
 			}
 
@@ -723,7 +721,6 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
 			h.pageTrees.treeTaxonomyEntries.DeletePrefix("")
 
 			if delete {
-
 				_, ok := h.pageTrees.treePages.LongestPrefixAll(pathInfo.Base())
 				if ok {
 					h.pageTrees.treePages.DeleteAll(pathInfo.Base())
diff --git a/hugolib/pages_capture.go b/hugolib/pages_capture.go
index b7da065fdc5..a7f8faaf0b4 100644
--- a/hugolib/pages_capture.go
+++ b/hugolib/pages_capture.go
@@ -196,6 +196,11 @@ func (c *pagesCollector) Collect() (collectErr error) {
 
 						return id.p.Dir() == fim.Meta().PathInfo.Dir()
 					}
+
+					if fim.Meta().PathInfo.IsLeafBundle() && id.p.BundleType() == paths.PathTypeContentSingle {
+						return id.p.Dir() == fim.Meta().PathInfo.Dir()
+					}
+
 					return id.p.Path() == fim.Meta().PathInfo.Path()
 				})
 			}


Test patch:
diff --git a/hugolib/rebuild_test.go b/hugolib/rebuild_test.go
index 74b04fe0116..b1ebe14d53a 100644
--- a/hugolib/rebuild_test.go
+++ b/hugolib/rebuild_test.go
@@ -39,7 +39,7 @@ My Section Bundle Text 2 Content.
 ---
 title: "My Section Bundle Content"
 ---
-My Section Bundle Content.
+My Section Bundle Content Content.
 -- content/mysection/_index.md --
 ---
 title: "My Section"
@@ -68,7 +68,7 @@ Foo.
 func TestRebuildEditTextFileInLeafBundle(t *testing.T) {
 	b := TestRunning(t, rebuildFilesSimple)
 	b.AssertFileContent("public/mysection/mysectionbundle/index.html",
-		"Resources: 0:/mysection/mysectionbundle/mysectionbundletext.txt|My Section Bundle Text 2 Content.|1:|<p>My Section Bundle Content.</p>\n|$")
+		"Resources: 0:/mysection/mysectionbundle/mysectionbundletext.txt|My Section Bundle Text 2 Content.|1:|<p>My Section Bundle Content Content.</p>\n|$")
 
 	b.EditFileReplaceAll("content/mysection/mysectionbundle/mysectionbundletext.txt", "Content.", "Content Edited.").Build()
 	b.AssertFileContent("public/mysection/mysectionbundle/index.html",
@@ -109,6 +109,13 @@ func TestRebuildRenameTextFileInLeafBundle(t *testing.T) {
 	b.AssertRenderCountContent(3)
 }
 
+func TestRebuilEditContentFileInLeafBundle(t *testing.T) {
+	b := TestRunning(t, rebuildFilesSimple)
+	b.AssertFileContent("public/mysection/mysectionbundle/index.html", "My Section Bundle Content Content.")
+	b.EditFileReplaceAll("content/mysection/mysectionbundle/mysectionbundlecontent.md", "Content Content.", "Content Content Edited.").Build()
+	b.AssertFileContent("public/mysection/mysectionbundle/index.html", "My Section Bundle Content Content Edited.")
+}
+
 func TestRebuildRenameTextFileInBranchBundle(t *testing.T) {
 	b := TestRunning(t, rebuildFilesSimple)
 	b.AssertFileContent("public/mysection/index.html", "My Section")