resourceTrees doctree.MutableTrees
}
-// 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(p *paths.Path) []identity.Identity {
- ids := t.collectIdentitiesFor(p.Base())
+// collectAndMarkStaleIdentities collects all identities from in all trees matching the given key.
+// We currently re-read all page/resources for all languages that share the same path,
+// so we mark all entries as stale (which will trigger cache invalidation), then
+// return the first.
+func (t *pageTrees) collectAndMarkStaleIdentities(p *paths.Path) []identity.Identity {
+ ids := t.collectAndMarkStaleIdentitiesFor(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 {
+ key := p.ForBundleType(paths.PathTypeContentResource).Base()
+ tree := t.treeResources
+ if n := tree.Get(key); n != nil {
n.ForEeachIdentity(func(id identity.Identity) bool {
ids = append(ids, id)
return false
})
+ if n, ok := tree.GetRaw(key); ok {
+ n.MarkStale()
+ }
}
}
return ids
}
-func (t *pageTrees) collectIdentitiesFor(key string) []identity.Identity {
+func (t *pageTrees) collectAndMarkStaleIdentitiesFor(key string) []identity.Identity {
var ids []identity.Identity
- if n := t.treePages.Get(key); n != nil {
+ tree := t.treePages
+ if n := tree.Get(key); n != nil {
n.ForEeachIdentity(func(id identity.Identity) bool {
ids = append(ids, id)
return false
})
+ if n, ok := tree.GetRaw(key); ok {
+ n.MarkStale()
+ }
}
- if n := t.treeResources.Get(key); n != nil {
+ tree = t.treeResources
+ if n := tree.Get(key); n != nil {
n.ForEeachIdentity(func(id identity.Identity) bool {
ids = append(ids, id)
return false
})
+ if n, ok := tree.GetRaw(key); ok {
+ n.MarkStale()
+ }
}
return ids
func (n contentNodeIs) MarkStale() {
for _, nn := range n {
- if nn != nil {
- nn.MarkStale()
- }
+ resource.MarkStale(nn)
}
}
if !ok {
panic(fmt.Sprintf("unknown type %T", new))
}
+ resource.MarkStale(vv[newp.s.languagei])
vv[newp.s.languagei] = new
return vv
case *resourceSource:
if !ok {
panic(fmt.Sprintf("unknown type %T", new))
}
+ resource.MarkStale(vv[newp.LangIndex()])
vv[newp.LangIndex()] = newp
return vv
default:
)
for _, id := range changes {
- if staler, ok := id.(resource.Staler); ok {
- h.Log.Trace(logg.StringFunc(func() string { return fmt.Sprintf("Marking stale: %s (%T)\n", id, id) }))
+ if staler, ok := id.(resource.Staler); ok && !staler.IsStale() {
+ var msgDetail string
+ if p, ok := id.(*pageState); ok && p.File() != nil {
+ msgDetail = fmt.Sprintf(" (%s)", p.File().Filename())
+ }
+ h.Log.Trace(logg.StringFunc(func() string { return fmt.Sprintf("Marking stale: %s (%T)%s\n", id, id, msgDetail) }))
staler.MarkStale()
}
}
b.AssertFileContent("public/index.html", "Hello: Hugo")
}
+func TestRebuildEditContentNonDefaultLanguage(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableLiveReload = true
+defaultContentLanguage = "en"
+defaultContentLanguageInSubdir = true
+[languages]
+[languages.en]
+weight = 1
+[languages.nn]
+weight = 2
+-- content/p1/index.en.md --
+---
+title: "P1 en"
+---
+P1 en.
+-- content/p1/b.en.md --
+---
+title: "B en"
+---
+B en.
+-- content/p1/f1.en.txt --
+F1 en
+-- content/p1/index.nn.md --
+---
+title: "P1 nn"
+---
+P1 nn.
+-- content/p1/b.nn.md --
+---
+title: "B nn"
+---
+B nn.
+-- content/p1/f1.nn.txt --
+F1 nn
+-- layouts/_default/single.html --
+Single: {{ .Title }}|{{ .Content }}|Bundled File: {{ with .Resources.GetMatch "f1.*" }}{{ .Content }}{{ end }}|Bundled Page: {{ with .Resources.GetMatch "b.*" }}{{ .Content }}{{ end }}|
+`
+
+ b := TestRunning(t, files)
+
+ b.AssertFileContent("public/nn/p1/index.html", "Single: P1 nn|<p>P1 nn.</p>", "F1 nn|")
+ b.EditFileReplaceAll("content/p1/index.nn.md", "P1 nn.", "P1 nn edit.").Build()
+ b.AssertFileContent("public/nn/p1/index.html", "Single: P1 nn|<p>P1 nn edit.</p>\n|")
+ b.EditFileReplaceAll("content/p1/f1.nn.txt", "F1 nn", "F1 nn edit.").Build()
+ b.AssertFileContent("public/nn/p1/index.html", "Bundled File: F1 nn edit.")
+ b.EditFileReplaceAll("content/p1/b.nn.md", "B nn.", "B nn edit.").Build()
+ b.AssertFileContent("public/nn/p1/index.html", "B nn edit.")
+}
+
func TestRebuildVariationsAssetsSassImport(t *testing.T) {
if !htesting.IsCI() {
t.Skip("skip CI only")