aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2018-03-11 18:59:11 +0100
committerBjørn Erik Pedersen <[email protected]>2018-03-11 21:32:05 +0100
commitce6e4310febf5659392a41b543594382441f3681 (patch)
treef9ca38eeadc3b61d7fa0828db28efef921e2dd3d
parent95d62004a07d8bb6d2b94a56112fd419db7eeb65 (diff)
downloadhugo-ce6e4310febf5659392a41b543594382441f3681.tar.gz
hugo-ce6e4310febf5659392a41b543594382441f3681.zip
Refactor the GitInfo into the date handlers
Fixes #4495
-rw-r--r--hugolib/gitinfo.go46
-rw-r--r--hugolib/hugo_sites.go19
-rw-r--r--hugolib/hugo_sites_build.go2
-rw-r--r--hugolib/page.go28
-rw-r--r--hugolib/page_test.go32
-rw-r--r--hugolib/pagemeta/page_frontmatter.go20
-rw-r--r--hugolib/pagemeta/page_frontmatter_test.go86
-rw-r--r--hugolib/testsite/content/first-post.md4
8 files changed, 148 insertions, 89 deletions
diff --git a/hugolib/gitinfo.go b/hugolib/gitinfo.go
index bfcfa9a42..affa9cea8 100644
--- a/hugolib/gitinfo.go
+++ b/hugolib/gitinfo.go
@@ -19,51 +19,41 @@ import (
"strings"
"github.com/bep/gitmap"
+ "github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/helpers"
)
-func (h *HugoSites) assembleGitInfo() {
- if !h.Cfg.GetBool("enableGitInfo") {
- return
+type gitInfo struct {
+ contentDir string
+ repo *gitmap.GitRepo
+}
+
+func (g *gitInfo) forPage(p *Page) (*gitmap.GitInfo, bool) {
+ if g == nil {
+ return nil, false
}
+ name := path.Join(g.contentDir, filepath.ToSlash(p.Path()))
+ return g.repo.Files[name], true
+}
+func newGitInfo(cfg config.Provider) (*gitInfo, error) {
var (
- workingDir = h.Cfg.GetString("workingDir")
- contentDir = h.Cfg.GetString("contentDir")
+ workingDir = cfg.GetString("workingDir")
+ contentDir = cfg.GetString("contentDir")
)
gitRepo, err := gitmap.Map(workingDir, "")
if err != nil {
- h.Log.ERROR.Printf("Got error reading Git log: %s", err)
- return
+ return nil, err
}
- gitMap := gitRepo.Files
repoPath := filepath.FromSlash(gitRepo.TopLevelAbsPath)
-
// The Hugo site may be placed in a sub folder in the Git repo,
// one example being the Hugo docs.
// We have to find the root folder to the Hugo site below the Git root.
contentRoot := strings.TrimPrefix(workingDir, repoPath)
contentRoot = strings.TrimPrefix(contentRoot, helpers.FilePathSeparator)
+ contentDir = path.Join(filepath.ToSlash(contentRoot), contentDir)
- s := h.Sites[0]
-
- for _, p := range s.AllPages {
- if p.Path() == "" {
- // Home page etc. with no content file.
- continue
- }
- // Git normalizes file paths on this form:
- filename := path.Join(filepath.ToSlash(contentRoot), contentDir, filepath.ToSlash(p.Path()))
- g, ok := gitMap[filename]
- if !ok {
- h.Log.WARN.Printf("Failed to find GitInfo for %q", filename)
- continue
- }
-
- p.GitInfo = g
- p.Lastmod = p.GitInfo.AuthorDate
- }
-
+ return &gitInfo{contentDir: contentDir, repo: gitRepo}, nil
}
diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go
index 6c2a5c153..4e802270d 100644
--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -47,6 +47,9 @@ type HugoSites struct {
// Keeps track of bundle directories and symlinks to enable partial rebuilding.
ContentChanges *contentChangeMap
+
+ // If enabled, keeps a revision map for all content.
+ gitInfo *gitInfo
}
func (h *HugoSites) IsMultihost() bool {
@@ -146,9 +149,25 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) {
h.Deps = sites[0].Deps
+ if err := h.initGitInfo(); err != nil {
+ return nil, err
+ }
+
return h, nil
}
+func (h *HugoSites) initGitInfo() error {
+ if h.Cfg.GetBool("enableGitInfo") {
+ gi, err := newGitInfo(h.Cfg)
+ if err != nil {
+ h.Log.ERROR.Println("Failed to read Git log:", err)
+ } else {
+ h.gitInfo = gi
+ }
+ }
+ return nil
+}
+
func applyDepsIfNeeded(cfg deps.DepsCfg, sites ...*Site) error {
if cfg.TemplateProvider == nil {
cfg.TemplateProvider = tplimpl.DefaultTemplateProvider
diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go
index 8f03f589f..c8affe15a 100644
--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -165,8 +165,6 @@ func (h *HugoSites) assemble(config *BuildCfg) error {
}
if config.whatChanged.source {
- h.assembleGitInfo()
-
for _, s := range h.Sites {
if err := s.buildSiteMeta(); err != nil {
return err
diff --git a/hugolib/page.go b/hugolib/page.go
index 2274aa84a..f8f8f9958 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -1119,13 +1119,20 @@ func (p *Page) update(frontmatter map[string]interface{}) error {
mtime = p.Source.FileInfo().ModTime()
}
+ var gitAuthorDate time.Time
+ if p.GitInfo != nil {
+ gitAuthorDate = p.GitInfo.AuthorDate
+ }
+
descriptor := &pagemeta.FrontMatterDescriptor{
- Frontmatter: frontmatter,
- Params: p.params,
- Dates: &p.PageDates,
- PageURLs: &p.URLPath,
- BaseFilename: p.BaseFileName(),
- ModTime: mtime}
+ Frontmatter: frontmatter,
+ Params: p.params,
+ Dates: &p.PageDates,
+ PageURLs: &p.URLPath,
+ BaseFilename: p.BaseFileName(),
+ ModTime: mtime,
+ GitAuthorDate: gitAuthorDate,
+ }
// Handle the date separately
// TODO(bep) we need to "do more" in this area so this can be split up and
@@ -1579,6 +1586,15 @@ func (p *Page) parse(reader io.Reader) error {
meta = map[string]interface{}{}
}
+ if p.s != nil && p.s.owner != nil {
+ gi, enabled := p.s.owner.gitInfo.forPage(p)
+ if gi != nil {
+ p.GitInfo = gi
+ } else if enabled {
+ p.s.Log.WARN.Printf("Failed to find GitInfo for page %q", p.Path())
+ }
+ }
+
return p.update(meta)
}
diff --git a/hugolib/page_test.go b/hugolib/page_test.go
index 905793ca6..875c5bdde 100644
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -18,6 +18,7 @@ import (
"fmt"
"html/template"
"os"
+
"path/filepath"
"reflect"
"sort"
@@ -25,6 +26,11 @@ import (
"testing"
"time"
+ "github.com/gohugoio/hugo/hugofs"
+ "github.com/spf13/afero"
+
+ "github.com/spf13/viper"
+
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
"github.com/spf13/cast"
@@ -904,6 +910,32 @@ func TestPageWithDate(t *testing.T) {
checkPageDate(t, p, d)
}
+func TestPageWithLastmodFromGitInfo(t *testing.T) {
+ assrt := require.New(t)
+
+ // We need to use the OS fs for this.
+ cfg := viper.New()
+ fs := hugofs.NewFrom(hugofs.Os, cfg)
+ fs.Destination = &afero.MemMapFs{}
+
+ cfg.Set("frontmatter", map[string]interface{}{
+ "lastmod": []string{":git", "lastmod"},
+ })
+
+ cfg.Set("enableGitInfo", true)
+
+ assrt.NoError(loadDefaultSettingsFor(cfg))
+
+ wd, err := os.Getwd()
+ assrt.NoError(err)
+ cfg.Set("workingDir", filepath.Join(wd, "testsite"))
+
+ s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{SkipRender: true})
+
+ assrt.Len(s.RegularPages, 1)
+ assrt.Equal("2018-02-28", s.RegularPages[0].Lastmod.Format("2006-01-02"))
+}
+
func TestPageWithFrontMatterConfig(t *testing.T) {
t.Parallel()
diff --git a/hugolib/pagemeta/page_frontmatter.go b/hugolib/pagemeta/page_frontmatter.go
index 5e60a47d0..8bfc4e837 100644
--- a/hugolib/pagemeta/page_frontmatter.go
+++ b/hugolib/pagemeta/page_frontmatter.go
@@ -56,6 +56,9 @@ type FrontMatterDescriptor struct {
// The content file's mod time.
ModTime time.Time
+ // May be set from the author date in Git.
+ GitAuthorDate time.Time
+
// The below are pointers to values on Page and will be modified.
// This is the Page's params.
@@ -175,13 +178,16 @@ const (
// Gets date from file OS mod time.
fmModTime = ":filemodtime"
+
+ // Gets date from Git
+ fmGitAuthorDate = ":git"
)
// This is the config you get when doing nothing.
func newDefaultFrontmatterConfig() frontmatterConfig {
return frontmatterConfig{
date: []string{fmDate, fmPubDate, fmLastmod},
- lastmod: []string{fmLastmod, fmDate, fmPubDate},
+ lastmod: []string{fmGitAuthorDate, fmLastmod, fmDate, fmPubDate},
publishDate: []string{fmPubDate, fmDate},
expiryDate: []string{fmExpiryDate},
}
@@ -348,6 +354,8 @@ func (f FrontMatterHandler) createDateHandler(identifiers []string, setter func(
handlers = append(handlers, h.newDateFilenameHandler(setter))
case fmModTime:
handlers = append(handlers, h.newDateModTimeHandler(setter))
+ case fmGitAuthorDate:
+ handlers = append(handlers, h.newDateGitAuthorDateHandler(setter))
default:
handlers = append(handlers, h.newDateFieldHandler(identifier, setter))
}
@@ -410,3 +418,13 @@ func (f *frontmatterFieldHandlers) newDateModTimeHandler(setter func(d *FrontMat
return true, nil
}
}
+
+func (f *frontmatterFieldHandlers) newDateGitAuthorDateHandler(setter func(d *FrontMatterDescriptor, t time.Time)) frontMatterFieldHandler {
+ return func(d *FrontMatterDescriptor) (bool, error) {
+ if d.GitAuthorDate.IsZero() {
+ return false, nil
+ }
+ setter(d, d.GitAuthorDate)
+ return true, nil
+ }
+}
diff --git a/hugolib/pagemeta/page_frontmatter_test.go b/hugolib/pagemeta/page_frontmatter_test.go
index 5372a4f3a..03f4c2f84 100644
--- a/hugolib/pagemeta/page_frontmatter_test.go
+++ b/hugolib/pagemeta/page_frontmatter_test.go
@@ -15,6 +15,7 @@ package pagemeta
import (
"fmt"
+ "strings"
"testing"
"time"
@@ -94,7 +95,7 @@ func TestFrontMatterNewConfig(t *testing.T) {
fc, err = newFrontmatterConfig(cfg)
assert.NoError(err)
assert.Equal([]string{"date", "publishdate", "pubdate", "published", "lastmod", "modified"}, fc.date)
- assert.Equal([]string{"lastmod", "modified", "date", "publishdate", "pubdate", "published"}, fc.lastmod)
+ assert.Equal([]string{":git", "lastmod", "modified", "date", "publishdate", "pubdate", "published"}, fc.lastmod)
assert.Equal([]string{"expirydate", "unpublishdate"}, fc.expiryDate)
assert.Equal([]string{"publishdate", "pubdate", "published", "date"}, fc.publishDate)
@@ -108,69 +109,50 @@ func TestFrontMatterNewConfig(t *testing.T) {
fc, err = newFrontmatterConfig(cfg)
assert.NoError(err)
assert.Equal([]string{"d1", "date", "publishdate", "pubdate", "published", "lastmod", "modified"}, fc.date)
- assert.Equal([]string{"d2", "lastmod", "modified", "date", "publishdate", "pubdate", "published"}, fc.lastmod)
+ assert.Equal([]string{"d2", ":git", "lastmod", "modified", "date", "publishdate", "pubdate", "published"}, fc.lastmod)
assert.Equal([]string{"d3", "expirydate", "unpublishdate"}, fc.expiryDate)
assert.Equal([]string{"d4", "publishdate", "pubdate", "published", "date"}, fc.publishDate)
}
-func TestFrontMatterDatesFilenameModTime(t *testing.T) {
+func TestFrontMatterDatesHandlers(t *testing.T) {
assert := require.New(t)
- cfg := viper.New()
-
- cfg.Set("frontmatter", map[string]interface{}{
- "date": []string{":fileModTime", "date"},
- })
-
- handler, err := NewFrontmatterHandler(nil, cfg)
- assert.NoError(err)
-
- d1, _ := time.Parse("2006-01-02", "2018-02-01")
- d2, _ := time.Parse("2006-01-02", "2018-02-02")
-
- d := newTestFd()
- d.ModTime = d1
- d.Frontmatter["date"] = d2
- assert.NoError(handler.HandleDates(d))
- assert.Equal(d1, d.Dates.Date)
- assert.Equal(d2, d.Params["date"])
-
- d = newTestFd()
- d.Frontmatter["date"] = d2
- assert.NoError(handler.HandleDates(d))
- assert.Equal(d2, d.Dates.Date)
- assert.Equal(d2, d.Params["date"])
-
-}
-
-func TestFrontMatterDatesFilename(t *testing.T) {
- assert := require.New(t)
+ for _, handlerID := range []string{":filename", ":fileModTime", ":git"} {
- cfg := viper.New()
-
- cfg.Set("frontmatter", map[string]interface{}{
- "date": []string{":filename", "date"},
- })
+ cfg := viper.New()
- handler, err := NewFrontmatterHandler(nil, cfg)
- assert.NoError(err)
+ cfg.Set("frontmatter", map[string]interface{}{
+ "date": []string{handlerID, "date"},
+ })
- d1, _ := time.Parse("2006-01-02", "2018-02-01")
- d2, _ := time.Parse("2006-01-02", "2018-02-02")
+ handler, err := NewFrontmatterHandler(nil, cfg)
+ assert.NoError(err)
- d := newTestFd()
- d.BaseFilename = "2018-02-01-page.md"
- d.Frontmatter["date"] = d2
- assert.NoError(handler.HandleDates(d))
- assert.Equal(d1, d.Dates.Date)
- assert.Equal(d2, d.Params["date"])
+ d1, _ := time.Parse("2006-01-02", "2018-02-01")
+ d2, _ := time.Parse("2006-01-02", "2018-02-02")
+
+ d := newTestFd()
+ switch strings.ToLower(handlerID) {
+ case ":filename":
+ d.BaseFilename = "2018-02-01-page.md"
+ case ":filemodtime":
+ d.ModTime = d1
+ case ":git":
+ d.GitAuthorDate = d1
+ }
+ d.Frontmatter["date"] = d2
+ assert.NoError(handler.HandleDates(d))
+ assert.Equal(d1, d.Dates.Date)
+ assert.Equal(d2, d.Params["date"])
+
+ d = newTestFd()
+ d.Frontmatter["date"] = d2
+ assert.NoError(handler.HandleDates(d))
+ assert.Equal(d2, d.Dates.Date)
+ assert.Equal(d2, d.Params["date"])
- d = newTestFd()
- d.Frontmatter["date"] = d2
- assert.NoError(handler.HandleDates(d))
- assert.Equal(d2, d.Dates.Date)
- assert.Equal(d2, d.Params["date"])
+ }
}
func TestFrontMatterDatesCustomConfig(t *testing.T) {
diff --git a/hugolib/testsite/content/first-post.md b/hugolib/testsite/content/first-post.md
new file mode 100644
index 000000000..4a8007946
--- /dev/null
+++ b/hugolib/testsite/content/first-post.md
@@ -0,0 +1,4 @@
+---
+title: "My First Post"
+lastmod: 2018-02-28
+--- \ No newline at end of file