summaryrefslogtreecommitdiffstats
path: root/hugolib
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2020-01-22 11:57:23 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2020-01-23 11:50:02 +0100
commit17af79a03e249a731cf5634ffea23ca00774333d (patch)
tree66596a159aa57c948f1ffe272e5cd8ab86c7c1bf /hugolib
parent2fefc01606fddb119f368c89fb2dedd452ad6547 (diff)
Fix 0.62.1 server rebuild slowdown regression
Fixes #6784
Diffstat (limited to 'hugolib')
-rw-r--r--hugolib/content_render_hooks_test.go24
-rw-r--r--hugolib/filesystems/basefs.go13
-rw-r--r--hugolib/hugo_modules_test.go120
-rw-r--r--hugolib/hugo_sites.go16
-rw-r--r--hugolib/hugo_sites_build.go2
-rw-r--r--hugolib/page__per_output.go2
-rw-r--r--hugolib/testhelpers_test.go9
7 files changed, 175 insertions, 11 deletions
diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go
index 8aba1dd8c..5290ebcbd 100644
--- a/hugolib/content_render_hooks_test.go
+++ b/hugolib/content_render_hooks_test.go
@@ -14,7 +14,10 @@
package hugolib
import (
+ "fmt"
"testing"
+
+ qt "github.com/frankban/quicktest"
)
func TestRenderHooks(t *testing.T) {
@@ -118,7 +121,20 @@ title: With RenderString
{{< myshortcode5 >}}Inner Link: [Inner Link](https://www.gohugo.io "Hugo's Homepage"){{< /myshortcode5 >}}
`)
- b.Build(BuildCfg{})
+
+ for i := 1; i <= 30; i++ {
+ // Add some content with no shortcodes or links, i.e no templates needed.
+ b.WithContent(fmt.Sprintf("blog/notempl%d.md", i), `---
+title: No Template
+---
+
+## Content
+`)
+ }
+ counters := &testCounters{}
+ b.Build(BuildCfg{testCounters: counters})
+ b.Assert(int(counters.contentRenderCounter), qt.Equals, 50)
+
b.AssertFileContent("public/blog/p1/index.html", `
<p>Cool Page|https://www.google.com|Title: Google's Homepage|Text: First Link|END</p>
Text: Second
@@ -149,7 +165,11 @@ SHORT3|
"layouts/shortcodes/myshortcode3.html", `SHORT3_EDITED|`,
)
- b.Build(BuildCfg{})
+ counters = &testCounters{}
+ b.Build(BuildCfg{testCounters: counters})
+ // Make sure that only content using the changed templates are re-rendered.
+ b.Assert(int(counters.contentRenderCounter), qt.Equals, 7)
+
b.AssertFileContent("public/customview/p1/index.html", `.Render: myrender: Custom View|P4: PARTIAL4_EDITED`)
b.AssertFileContent("public/blog/p1/index.html", `<p>EDITED: https://www.google.com|</p>`, "SHORT3_EDITED|")
b.AssertFileContent("public/blog/p2/index.html", `PARTIAL1_EDITED`)
diff --git a/hugolib/filesystems/basefs.go b/hugolib/filesystems/basefs.go
index cf9ff3c38..5cede88d0 100644
--- a/hugolib/filesystems/basefs.go
+++ b/hugolib/filesystems/basefs.go
@@ -295,21 +295,16 @@ func (d *SourceFilesystem) Contains(filename string) bool {
return false
}
-// Path returns the relative path to the given filename if it is a member of
+// Path returns the mount relative path to the given filename if it is a member of
// of the current filesystem, an empty string if not.
func (d *SourceFilesystem) Path(filename string) string {
for _, dir := range d.Dirs {
meta := dir.Meta()
- if !dir.IsDir() {
- if filename == meta.Filename() {
- return meta.PathFile()
- }
- continue
- }
-
if strings.HasPrefix(filename, meta.Filename()) {
p := strings.TrimPrefix(strings.TrimPrefix(filename, meta.Filename()), filePathSeparator)
- p = path.Join(meta.PathFile(), p)
+ if mountRoot := meta.MountRoot(); mountRoot != "" {
+ return filepath.Join(mountRoot, p)
+ }
return p
}
}
diff --git a/hugolib/hugo_modules_test.go b/hugolib/hugo_modules_test.go
index 5c2b46b30..4b71a54c8 100644
--- a/hugolib/hugo_modules_test.go
+++ b/hugolib/hugo_modules_test.go
@@ -668,6 +668,126 @@ Readme Edit
}
+func TestMountsPaths(t *testing.T) {
+ c := qt.New(t)
+
+ type test struct {
+ b *sitesBuilder
+ clean func()
+ workingDir string
+ }
+
+ prepare := func(c *qt.C, mounts string) test {
+ workingDir, clean, err := htesting.CreateTempDir(hugofs.Os, "hugo-mounts-paths")
+ c.Assert(err, qt.IsNil)
+
+ configTemplate := `
+baseURL = "https://example.com"
+title = "My Modular Site"
+workingDir = %q
+
+%s
+
+`
+ config := fmt.Sprintf(configTemplate, workingDir, mounts)
+ config = strings.Replace(config, "WORKING_DIR", workingDir, -1)
+
+ b := newTestSitesBuilder(c).Running()
+
+ b.Fs = hugofs.NewDefault(viper.New())
+
+ os.MkdirAll(filepath.Join(workingDir, "content", "blog"), 0777)
+
+ b.WithWorkingDir(workingDir).WithConfigFile("toml", config)
+
+ return test{
+ b: b,
+ clean: clean,
+ workingDir: workingDir,
+ }
+
+ }
+
+ c.Run("Default", func(c *qt.C) {
+ mounts := ``
+
+ test := prepare(c, mounts)
+ b := test.b
+ defer test.clean()
+
+ b.WithContent("blog/p1.md", `---
+title: P1
+---`)
+
+ b.Build(BuildCfg{})
+
+ p := b.GetPage("blog/p1.md")
+ f := p.File().FileInfo().Meta()
+ b.Assert(filepath.ToSlash(f.Path()), qt.Equals, "blog/p1.md")
+ b.Assert(filepath.ToSlash(f.PathFile()), qt.Equals, "content/blog/p1.md")
+
+ b.Assert(b.H.BaseFs.Layouts.Path(filepath.Join(test.workingDir, "layouts", "_default", "single.html")), qt.Equals, filepath.FromSlash("_default/single.html"))
+
+ })
+
+ c.Run("Mounts", func(c *qt.C) {
+ absDir, clean, err := htesting.CreateTempDir(hugofs.Os, "hugo-mounts-paths-abs")
+ c.Assert(err, qt.IsNil)
+ defer clean()
+
+ mounts := `[module]
+ [[module.mounts]]
+ source = "README.md"
+ target = "content/_index.md"
+ [[module.mounts]]
+ source = "mycontent"
+ target = "content/blog"
+ [[module.mounts]]
+ source = "subdir/mypartials"
+ target = "layouts/partials"
+ [[module.mounts]]
+ source = %q
+ target = "layouts/shortcodes"
+`
+ mounts = fmt.Sprintf(mounts, filepath.Join(absDir, "/abs/myshortcodes"))
+
+ test := prepare(c, mounts)
+ b := test.b
+ defer test.clean()
+
+ subContentDir := filepath.Join(test.workingDir, "mycontent", "sub")
+ os.MkdirAll(subContentDir, 0777)
+ myPartialsDir := filepath.Join(test.workingDir, "subdir", "mypartials")
+ os.MkdirAll(myPartialsDir, 0777)
+
+ absShortcodesDir := filepath.Join(absDir, "abs", "myshortcodes")
+ os.MkdirAll(absShortcodesDir, 0777)
+
+ b.WithSourceFile("README.md", "---\ntitle: Readme\n---")
+ b.WithSourceFile("mycontent/sub/p1.md", "---\ntitle: P1\n---")
+
+ b.WithSourceFile(filepath.Join(absShortcodesDir, "myshort.html"), "MYSHORT")
+ b.WithSourceFile(filepath.Join(myPartialsDir, "mypartial.html"), "MYPARTIAL")
+
+ b.Build(BuildCfg{})
+
+ p1_1 := b.GetPage("/blog/sub/p1.md")
+ p1_2 := b.GetPage("/mycontent/sub/p1.md")
+ b.Assert(p1_1, qt.Not(qt.IsNil))
+ b.Assert(p1_2, qt.Equals, p1_1)
+
+ f := p1_1.File().FileInfo().Meta()
+ b.Assert(filepath.ToSlash(f.Path()), qt.Equals, "blog/sub/p1.md")
+ b.Assert(filepath.ToSlash(f.PathFile()), qt.Equals, "mycontent/sub/p1.md")
+ b.Assert(b.H.BaseFs.Layouts.Path(filepath.Join(myPartialsDir, "mypartial.html")), qt.Equals, filepath.FromSlash("partials/mypartial.html"))
+ b.Assert(b.H.BaseFs.Layouts.Path(filepath.Join(absShortcodesDir, "myshort.html")), qt.Equals, filepath.FromSlash("shortcodes/myshort.html"))
+ b.Assert(b.H.BaseFs.Content.Path(filepath.Join(subContentDir, "p1.md")), qt.Equals, filepath.FromSlash("blog/sub/p1.md"))
+ b.Assert(b.H.BaseFs.Content.Path(filepath.Join(test.workingDir, "README.md")), qt.Equals, filepath.FromSlash("_index.md"))
+
+ })
+
+}
+
// https://github.com/gohugoio/hugo/issues/6299
func TestSiteWithGoModButNoModules(t *testing.T) {
t.Parallel()
diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go
index a0c62f01e..50694fbba 100644
--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -19,6 +19,7 @@ import (
"sort"
"strings"
"sync"
+ "sync/atomic"
"github.com/gohugoio/hugo/identity"
@@ -82,6 +83,19 @@ type HugoSites struct {
init *hugoSitesInit
*fatalErrorHandler
+ *testCounters
+}
+
+// Only used in tests.
+type testCounters struct {
+ contentRenderCounter uint64
+}
+
+func (h *testCounters) IncrContentRender() {
+ if h == nil {
+ return
+ }
+ atomic.AddUint64(&h.contentRenderCounter, 1)
}
type fatalErrorHandler struct {
@@ -579,6 +593,8 @@ type BuildCfg struct {
// Recently visited URLs. This is used for partial re-rendering.
RecentlyVisited map[string]bool
+
+ testCounters *testCounters
}
// shouldRender is used in the Fast Render Mode to determine if we need to re-render
diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go
index 901941bda..cf7b14311 100644
--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -66,6 +66,8 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
h.Metrics.Reset()
}
+ h.testCounters = config.testCounters
+
// Need a pointer as this may be modified.
conf := &config
diff --git a/hugolib/page__per_output.go b/hugolib/page__per_output.go
index 59440c7cb..330b0d75d 100644
--- a/hugolib/page__per_output.go
+++ b/hugolib/page__per_output.go
@@ -80,6 +80,8 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
}
initContent := func() (err error) {
+ p.s.h.IncrContentRender()
+
if p.cmap == nil {
// Nothing to do.
return nil
diff --git a/hugolib/testhelpers_test.go b/hugolib/testhelpers_test.go
index 376c0899c..7a87245a6 100644
--- a/hugolib/testhelpers_test.go
+++ b/hugolib/testhelpers_test.go
@@ -224,6 +224,9 @@ func (s *sitesBuilder) WithSourceFile(filenameContent ...string) *sitesBuilder {
func (s *sitesBuilder) absFilename(filename string) string {
filename = filepath.FromSlash(filename)
+ if filepath.IsAbs(filename) {
+ return filename
+ }
if s.workingDir != "" && !strings.HasPrefix(filename, s.workingDir) {
filename = filepath.Join(s.workingDir, filename)
}
@@ -736,6 +739,12 @@ func (s *sitesBuilder) CheckExists(filename string) bool {
return destinationExists(s.Fs, filepath.Clean(filename))
}
+func (s *sitesBuilder) GetPage(ref string) page.Page {
+ p, err := s.H.Sites[0].getPageNew(nil, ref)
+ s.Assert(err, qt.IsNil)
+ return p
+}
+
func newTestHelper(cfg config.Provider, fs *hugofs.Fs, t testing.TB) testHelper {
return testHelper{
Cfg: cfg,