diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-11-26 12:11:22 +0300 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-12-06 16:37:25 +0300 |
commit | 831d23cb4d1ca99cdc15ed31c8ee1f981497be8f (patch) | |
tree | 8fe47b1b1b9233448297f8015ce61bbb7da13fc7 | |
parent | 514e18dc27ce37a0e9a231741d616cf29d50d610 (diff) |
Add tpl/site and tpl/hugo
This means that the current `.Site` and ´.Hugo` is available as a globals, so you can do `site.IsServer`, `hugo.Version` etc.
Fixes #5470
Fixes #5467
Fixes #5503
35 files changed, 518 insertions, 162 deletions
diff --git a/.gitignore b/.gitignore index 568492d85..89244f128 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -hugo +/hugo docs/public* /.idea hugo.exe diff --git a/commands/commandeer.go b/commands/commandeer.go index cd2866a27..b722991ab 100644 --- a/commands/commandeer.go +++ b/commands/commandeer.go @@ -17,10 +17,11 @@ import ( "bytes" "errors" - "github.com/gohugoio/hugo/common/herrors" - "io/ioutil" + "github.com/gohugoio/hugo/common/herrors" + "github.com/gohugoio/hugo/common/hugo" + jww "github.com/spf13/jwalterweatherman" "os" @@ -105,7 +106,7 @@ func (c *commandeer) getErrorWithContext() interface{} { m := make(map[string]interface{}) m["Error"] = errors.New(removeErrorPrefixFromLog(c.logger.Errors())) - m["Version"] = hugoVersionString() + m["Version"] = hugo.BuildVersionString() fe := herrors.UnwrapErrorWithFileContext(c.buildErr) if fe != nil { @@ -379,7 +380,7 @@ func (c *commandeer) loadConfig(mustHaveConfigFile, running bool) error { if themeVersionMismatch { name := filepath.Base(dir) cfg.Logger.ERROR.Printf("%s theme does not support Hugo version %s. Minimum version required is %s\n", - strings.ToUpper(name), helpers.CurrentHugoVersion.ReleaseVersion(), minVersion) + strings.ToUpper(name), hugo.CurrentVersion.ReleaseVersion(), minVersion) } return nil diff --git a/commands/genman.go b/commands/genman.go index ac4eaf8d1..720046289 100644 --- a/commands/genman.go +++ b/commands/genman.go @@ -17,6 +17,7 @@ import ( "fmt" "strings" + "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/spf13/cobra" @@ -45,7 +46,7 @@ in the "man" directory under the current directory.`, header := &doc.GenManHeader{ Section: "1", Manual: "Hugo Manual", - Source: fmt.Sprintf("Hugo %s", helpers.CurrentHugoVersion), + Source: fmt.Sprintf("Hugo %s", hugo.CurrentVersion), } if !strings.HasSuffix(cc.genmandir, helpers.FilePathSeparator) { cc.genmandir += helpers.FilePathSeparator diff --git a/commands/hugo.go b/commands/hugo.go index 0bb15c3d1..759efc17b 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -23,6 +23,7 @@ import ( "sort" "sync/atomic" + "github.com/gohugoio/hugo/common/hugo" "github.com/pkg/errors" "github.com/gohugoio/hugo/common/herrors" @@ -1041,7 +1042,7 @@ func (c *commandeer) isThemeVsHugoVersionMismatch(fs afero.Fs) (dir string, mism } if minVersion, ok := tomlMeta["min_version"]; ok { - if helpers.CompareVersion(minVersion) > 0 { + if hugo.CompareVersion(minVersion) > 0 { return absThemeDir, true, fmt.Sprint(minVersion) } } diff --git a/commands/version.go b/commands/version.go index b85f53725..287950a2d 100644 --- a/commands/version.go +++ b/commands/version.go @@ -14,16 +14,9 @@ package commands import ( - "fmt" - "runtime" - "strings" - - jww "github.com/spf13/jwalterweatherman" - - "github.com/gohugoio/hugo/helpers" - "github.com/gohugoio/hugo/hugolib" - "github.com/gohugoio/hugo/resource/tocss/scss" + "github.com/gohugoio/hugo/common/hugo" "github.com/spf13/cobra" + jww "github.com/spf13/jwalterweatherman" ) var _ cmder = (*versionCmd)(nil) @@ -47,29 +40,5 @@ func newVersionCmd() *versionCmd { } func printHugoVersion() { - jww.FEEDBACK.Println(hugoVersionString()) -} - -func hugoVersionString() string { - program := "Hugo Static Site Generator" - - version := "v" + helpers.CurrentHugoVersion.String() - if hugolib.CommitHash != "" { - version += "-" + strings.ToUpper(hugolib.CommitHash) - } - if scss.Supports() { - version += "/extended" - } - - osArch := runtime.GOOS + "/" + runtime.GOARCH - - var buildDate string - if hugolib.BuildDate != "" { - buildDate = hugolib.BuildDate - } else { - buildDate = "unknown" - } - - return fmt.Sprintf("%s %s %s BuildDate: %s", program, version, osArch, buildDate) - + jww.FEEDBACK.Println(hugo.BuildVersionString()) } diff --git a/hugolib/hugo_info.go b/common/hugo/hugo.go index 303231edb..b93b10bf1 100644 --- a/hugolib/hugo_info.go +++ b/common/hugo/hugo.go @@ -11,13 +11,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package hugolib +package hugo import ( "fmt" "html/template" - - "github.com/gohugoio/hugo/helpers" ) var ( @@ -29,21 +27,19 @@ var ( BuildDate string ) -var hugoInfo *HugoInfo - -// HugoInfo contains information about the current Hugo environment -type HugoInfo struct { - Version helpers.HugoVersionString +// Info contains information about the current Hugo environment +type Info struct { + Version VersionString Generator template.HTML CommitHash string BuildDate string } -func init() { - hugoInfo = &HugoInfo{ - Version: helpers.CurrentHugoVersion.Version(), +func NewInfo() Info { + return Info{ + Version: CurrentVersion.Version(), CommitHash: CommitHash, BuildDate: BuildDate, - Generator: template.HTML(fmt.Sprintf(`<meta name="generator" content="Hugo %s" />`, helpers.CurrentHugoVersion.String())), + Generator: template.HTML(fmt.Sprintf(`<meta name="generator" content="Hugo %s" />`, CurrentVersion.String())), } } diff --git a/hugolib/hugo_info_test.go b/common/hugo/hugo_test.go index 0a34330ac..18a9b594f 100644 --- a/hugolib/hugo_info_test.go +++ b/common/hugo/hugo_test.go @@ -11,21 +11,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -package hugolib +package hugo import ( "fmt" "testing" - "github.com/gohugoio/hugo/helpers" "github.com/stretchr/testify/require" ) func TestHugoInfo(t *testing.T) { assert := require.New(t) - assert.Equal(helpers.CurrentHugoVersion.Version(), hugoInfo.Version) - assert.IsType(helpers.HugoVersionString(""), hugoInfo.Version) + hugoInfo := NewInfo() + + assert.Equal(CurrentVersion.Version(), hugoInfo.Version) + assert.IsType(VersionString(""), hugoInfo.Version) assert.Equal(CommitHash, hugoInfo.CommitHash) assert.Equal(BuildDate, hugoInfo.BuildDate) assert.Contains(hugoInfo.Generator, fmt.Sprintf("Hugo %s", hugoInfo.Version)) diff --git a/common/hugo/site.go b/common/hugo/site.go new file mode 100644 index 000000000..08391858a --- /dev/null +++ b/common/hugo/site.go @@ -0,0 +1,24 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hugo + +import "github.com/gohugoio/hugo/langs" + +// Site represents a site in the build. This is currently a very narrow interface, +// but the actual implementation will be richer, see hugolib.SiteInfo. +type Site interface { + Language() *langs.Language + IsServer() bool + Hugo() Info +} diff --git a/common/hugo/vars_extended.go b/common/hugo/vars_extended.go new file mode 100644 index 000000000..20683b804 --- /dev/null +++ b/common/hugo/vars_extended.go @@ -0,0 +1,18 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build extended + +package hugo + +var isExtended = true diff --git a/common/hugo/vars_regular.go b/common/hugo/vars_regular.go new file mode 100644 index 000000000..e1ece83fb --- /dev/null +++ b/common/hugo/vars_regular.go @@ -0,0 +1,18 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !extended + +package hugo + +var isExtended = false diff --git a/helpers/hugo.go b/common/hugo/version.go index 3ad4f9379..204f8f747 100644 --- a/helpers/hugo.go +++ b/common/hugo/version.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Hugo Authors. All rights reserved. +// Copyright 2018 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,18 +11,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -package helpers +package hugo import ( "fmt" + + "runtime" "strings" "github.com/gohugoio/hugo/compare" "github.com/spf13/cast" ) -// HugoVersion represents the Hugo build version. -type HugoVersion struct { +// Version represents the Hugo build version. +type Version struct { // Major and minor version. Number float32 @@ -35,34 +37,34 @@ type HugoVersion struct { } var ( - _ compare.Eqer = (*HugoVersionString)(nil) - _ compare.Comparer = (*HugoVersionString)(nil) + _ compare.Eqer = (*VersionString)(nil) + _ compare.Comparer = (*VersionString)(nil) ) -func (v HugoVersion) String() string { - return hugoVersion(v.Number, v.PatchLevel, v.Suffix) +func (v Version) String() string { + return version(v.Number, v.PatchLevel, v.Suffix) } // Version returns the Hugo version. -func (v HugoVersion) Version() HugoVersionString { - return HugoVersionString(v.String()) +func (v Version) Version() VersionString { + return VersionString(v.String()) } -// HugoVersionString represents a Hugo version string. -type HugoVersionString string +// VersionString represents a Hugo version string. +type VersionString string -func (h HugoVersionString) String() string { +func (h VersionString) String() string { return string(h) } // Compare implements the compare.Comparer interface. -func (h HugoVersionString) Compare(other interface{}) int { - v := MustParseHugoVersion(h.String()) +func (h VersionString) Compare(other interface{}) int { + v := MustParseVersion(h.String()) return compareVersionsWithSuffix(v.Number, v.PatchLevel, v.Suffix, other) } // Eq implements the compare.Eqer interface. -func (h HugoVersionString) Eq(other interface{}) bool { +func (h VersionString) Eq(other interface{}) bool { s, err := cast.ToStringE(other) if err != nil { return false @@ -72,9 +74,9 @@ func (h HugoVersionString) Eq(other interface{}) bool { var versionSuffixes = []string{"-test", "-DEV"} -// ParseHugoVersion parses a version string. -func ParseHugoVersion(s string) (HugoVersion, error) { - var vv HugoVersion +// ParseVersion parses a version string. +func ParseVersion(s string) (Version, error) { + var vv Version for _, suffix := range versionSuffixes { if strings.HasSuffix(s, suffix) { vv.Suffix = suffix @@ -90,10 +92,10 @@ func ParseHugoVersion(s string) (HugoVersion, error) { return vv, nil } -// MustParseHugoVersion parses a version string +// MustParseVersion parses a version string // and panics if any error occurs. -func MustParseHugoVersion(s string) HugoVersion { - vv, err := ParseHugoVersion(s) +func MustParseVersion(s string) Version { + vv, err := ParseVersion(s) if err != nil { panic(err) } @@ -101,36 +103,54 @@ func MustParseHugoVersion(s string) HugoVersion { } // ReleaseVersion represents the release version. -func (v HugoVersion) ReleaseVersion() HugoVersion { +func (v Version) ReleaseVersion() Version { v.Suffix = "" return v } // Next returns the next Hugo release version. -func (v HugoVersion) Next() HugoVersion { - return HugoVersion{Number: v.Number + 0.01} +func (v Version) Next() Version { + return Version{Number: v.Number + 0.01} } // Prev returns the previous Hugo release version. -func (v HugoVersion) Prev() HugoVersion { - return HugoVersion{Number: v.Number - 0.01} +func (v Version) Prev() Version { + return Version{Number: v.Number - 0.01} } // NextPatchLevel returns the next patch/bugfix Hugo version. // This will be a patch increment on the previous Hugo version. -func (v HugoVersion) NextPatchLevel(level int) HugoVersion { - return HugoVersion{Number: v.Number - 0.01, PatchLevel: level} +func (v Version) NextPatchLevel(level int) Version { + return Version{Number: v.Number - 0.01, PatchLevel: level} } -// CurrentHugoVersion represents the current build version. -// This should be the only one. -var CurrentHugoVersion = HugoVersion{ - Number: 0.53, - PatchLevel: 0, - Suffix: "-DEV", +// BuildVersionString creates a version string. This is what you see when +// running "hugo version". +func BuildVersionString() string { + program := "Hugo Static Site Generator" + + version := "v" + CurrentVersion.String() + if CommitHash != "" { + version += "-" + strings.ToUpper(CommitHash) + } + if isExtended { + version += "/extended" + } + + osArch := runtime.GOOS + "/" + runtime.GOARCH + + var buildDate string + if BuildDate != "" { + buildDate = BuildDate + } else { + buildDate = "unknown" + } + + return fmt.Sprintf("%s %s %s BuildDate: %s", program, version, osArch, buildDate) + } -func hugoVersion(version float32, patchVersion int, suffix string) string { +func version(version float32, patchVersion int, suffix string) string { if patchVersion > 0 { return fmt.Sprintf("%.2f.%d%s", version, patchVersion, suffix) } @@ -142,7 +162,7 @@ func hugoVersion(version float32, patchVersion int, suffix string) string { // It returns -1 if the given version is less than, 0 if equal and 1 if greater than // the running version. func CompareVersion(version interface{}) int { - return compareVersionsWithSuffix(CurrentHugoVersion.Number, CurrentHugoVersion.PatchLevel, CurrentHugoVersion.Suffix, version) + return compareVersionsWithSuffix(CurrentVersion.Number, CurrentVersion.PatchLevel, CurrentVersion.Suffix, version) } func compareVersions(inVersion float32, inPatchVersion int, in interface{}) int { @@ -168,7 +188,7 @@ func compareVersionsWithSuffix(inVersion float32, inPatchVersion int, suffix str return -1 } - v, err := ParseHugoVersion(s) + v, err := ParseVersion(s) if err != nil { return -1 } diff --git a/common/hugo/version_current.go b/common/hugo/version_current.go new file mode 100644 index 000000000..0a42f3023 --- /dev/null +++ b/common/hugo/version_current.go @@ -0,0 +1,22 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hugo + +// CurrentVersion represents the current build version. +// This should be the only one. +var CurrentVersion = Version{ + Number: 0.53, + PatchLevel: 0, + Suffix: "-DEV", +} diff --git a/helpers/hugo_test.go b/common/hugo/version_test.go index 1c2d89619..fb28750ec 100644 --- a/helpers/hugo_test.go +++ b/common/hugo/version_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package helpers +package hugo import ( "testing" @@ -21,10 +21,10 @@ import ( ) func TestHugoVersion(t *testing.T) { - assert.Equal(t, "0.15-DEV", hugoVersion(0.15, 0, "-DEV")) - assert.Equal(t, "0.15.2-DEV", hugoVersion(0.15, 2, "-DEV")) + assert.Equal(t, "0.15-DEV", version(0.15, 0, "-DEV")) + assert.Equal(t, "0.15.2-DEV", version(0.15, 2, "-DEV")) - v := HugoVersion{Number: 0.21, PatchLevel: 0, Suffix: "-DEV"} + v := Version{Number: 0.21, PatchLevel: 0, Suffix: "-DEV"} require.Equal(t, v.ReleaseVersion().String(), "0.21") require.Equal(t, "0.21-DEV", v.String()) @@ -62,9 +62,9 @@ func TestCompareVersions(t *testing.T) { } func TestParseHugoVersion(t *testing.T) { - require.Equal(t, "0.25", MustParseHugoVersion("0.25").String()) - require.Equal(t, "0.25.2", MustParseHugoVersion("0.25.2").String()) - require.Equal(t, "0.25-test", MustParseHugoVersion("0.25-test").String()) - require.Equal(t, "0.25-DEV", MustParseHugoVersion("0.25-DEV").String()) + require.Equal(t, "0.25", MustParseVersion("0.25").String()) + require.Equal(t, "0.25.2", MustParseVersion("0.25.2").String()) + require.Equal(t, "0.25-test", MustParseVersion("0.25-test").String()) + require.Equal(t, "0.25-DEV", MustParseVersion("0.25-DEV").String()) } diff --git a/deps/deps.go b/deps/deps.go index de6d8b52a..46f4f7730 100644 --- a/deps/deps.go +++ b/deps/deps.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" "github.com/gohugoio/hugo/cache/filecache" + "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" @@ -62,8 +63,12 @@ type Deps struct { // The translation func to use Translate func(translationID string, args ...interface{}) string `json:"-"` + // The language in use. TODO(bep) consolidate with site Language *langs.Language + // The site building. + Site hugo.Site + // All the output formats available for the current site. OutputFormatsConfig output.Formats @@ -230,6 +235,7 @@ func New(cfg DepsCfg) (*Deps, error) { ResourceSpec: resourceSpec, Cfg: cfg.Language, Language: cfg.Language, + Site: cfg.Site, FileCaches: fileCaches, BuildStartListeners: &Listeners{}, Timeout: time.Duration(timeoutms) * time.Millisecond, @@ -245,7 +251,7 @@ func New(cfg DepsCfg) (*Deps, error) { // ForLanguage creates a copy of the Deps with the language dependent // parts switched out. -func (d Deps) ForLanguage(cfg DepsCfg) (*Deps, error) { +func (d Deps) ForLanguage(cfg DepsCfg, onCreated func(d *Deps) error) (*Deps, error) { l := cfg.Language var err error @@ -259,6 +265,8 @@ func (d Deps) ForLanguage(cfg DepsCfg) (*Deps, error) { return nil, err } + d.Site = cfg.Site + // The resource cache is global so reuse. // TODO(bep) clean up these inits. resourceCache := d.ResourceSpec.ResourceCache @@ -271,6 +279,12 @@ func (d Deps) ForLanguage(cfg DepsCfg) (*Deps, error) { d.Cfg = l d.Language = l + if onCreated != nil { + if err = onCreated(&d); err != nil { + return nil, err + } + } + if err := d.translationProvider.Clone(&d); err != nil { return nil, err } @@ -299,6 +313,9 @@ type DepsCfg struct { // The language to use. Language *langs.Language + // The Site in use + Site hugo.Site + // The configuration to use. Cfg config.Provider diff --git a/goreleaser-extended.yml b/goreleaser-extended.yml index 31b52d7ba..004e94953 100644 --- a/goreleaser-extended.yml +++ b/goreleaser-extended.yml @@ -2,7 +2,7 @@ project_name: hugo_extended builds: - binary: hugo ldflags: - - -s -w -X github.com/gohugoio/hugo/hugolib.BuildDate={{.Date}} + - -s -w -X github.com/gohugoio/hugo/common/hugo.BuildDate={{.Date}} -X github.com/gohugoio/hugo/common/hugo.CommitHash={{ .ShortCommit }} - "-extldflags '-static'" env: - CGO_ENABLED=1 diff --git a/goreleaser.yml b/goreleaser.yml index d2cdf720e..0e9006019 100644 --- a/goreleaser.yml +++ b/goreleaser.yml @@ -2,7 +2,7 @@ project_name: hugo build: main: main.go binary: hugo - ldflags: -s -w -X github.com/gohugoio/hugo/hugolib.BuildDate={{.Date}} + ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.BuildDate={{.Date}} -X github.com/gohugoio/hugo/common/hugo.CommitHash={{ .ShortCommit }} env: - CGO_ENABLED=0 goos: diff --git a/helpers/general.go b/helpers/general.go index 43a921318..cfabab5a9 100644 --- a/helpers/general.go +++ b/helpers/general.go @@ -27,6 +27,8 @@ import ( "unicode" "unicode/utf8" + "github.com/gohugoio/hugo/common/hugo" + "github.com/gohugoio/hugo/hugofs" "github.com/spf13/afero" @@ -324,7 +326,7 @@ func InitLoggers() { // plenty of time to fix their templates. func Deprecated(object, item, alternative string, err bool) { if err { - DistinctErrorLog.Printf("%s's %s is deprecated and will be removed in Hugo %s. %s", object, item, CurrentHugoVersion.Next().ReleaseVersion(), alternative) + DistinctErrorLog.Printf("%s's %s is deprecated and will be removed in Hugo %s. %s", object, item, hugo.CurrentVersion.Next().ReleaseVersion(), alternative) } else { // Make sure the users see this while avoiding build breakage. This will not lead to an os.Exit(-1) diff --git a/htesting/test_structs.go b/htesting/test_structs.go new file mode 100644 index 000000000..168c848aa --- /dev/null +++ b/htesting/test_structs.go @@ -0,0 +1,51 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package htesting + +import ( + "github.com/gohugoio/hugo/common/hugo" + "github.com/gohugoio/hugo/langs" + "github.com/spf13/viper" +) + +type testSite struct { + h hugo.Info + l *langs.Language +} + +func (t testSite) Hugo() hugo.Info { + return t.h +} + +func (t testSite) IsServer() bool { + return false +} + +func (t testSite) Language() *langs.Language { + return t.l +} + +// NewTestHugoSite creates a new minimal test site. +func NewTestHugoSite() hugo.Site { + return testSite{ + h: hugo.NewInfo(), + l: langs.NewLanguage("en", newTestConfig()), + } +} + +func newTestConfig() *viper.Viper { + v := viper.New() + v.Set("contentDir", "content") + return v +} diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go index 9cc091927..043e049d7 100644 --- a/hugolib/hugo_sites.go +++ b/hugolib/hugo_sites.go @@ -21,12 +21,13 @@ import ( "strings" "sync" + "github.com/gohugoio/hugo/publisher" + "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/langs" - "github.com/gohugoio/hugo/publisher" "github.com/gohugoio/hugo/i18n" "github.com/gohugoio/hugo/tpl" @@ -224,6 +225,27 @@ func applyDeps(cfg deps.DepsCfg, sites ...*Site) error { continue } + onCreated := func(d *deps.Deps) error { + s.Deps = d + + // Set up the main publishing chain. + s.publisher = publisher.NewDestinationPublisher(d.PathSpec.BaseFs.PublishFs, s.outputFormatsConfig, s.mediaTypesConfig, cfg.Cfg.GetBool("minify")) + + if err := s.initializeSiteInfo(); err != nil { + return err + } + + d.Site = &s.Info + + siteConfig, err := loadSiteConfig(s.Language) + if err != nil { + return err + } + s.siteConfig = siteConfig + s.siteRefLinker, err = newSiteRefLinker(s.Language, s) + return err + } + cfg.Language = s.Language cfg.MediaTypes = s.mediaTypesConfig cfg.OutputFormats = s.outputFormatsConfig @@ -238,37 +260,23 @@ func applyDeps(cfg deps.DepsCfg, sites ...*Site) error { } d.OutputFormatsConfig = s.outputFormatsConfig - s.Deps = d + + if err := onCreated(d); err != nil { + return err + } if err = d.LoadResources(); err != nil { return err } } else { - d, err = d.ForLanguage(cfg) + d, err = d.ForLanguage(cfg, onCreated) if err != nil { return err } d.OutputFormatsConfig = s.outputFormatsConfig - s.Deps = d } - // Set up the main publishing chain. - s.publisher = publisher.NewDestinationPublisher(d.PathSpec.BaseFs.PublishFs, s.outputFormatsConfig, s.mediaTypesConfig, cfg.Cfg.GetBool("minify")) - - if err := s.initializeSiteInfo(); err != nil { - return err - } - - siteConfig, err := loadSiteConfig(s.Language) - if err != nil { - return err - } - s.siteConfig = siteConfig - s.siteRefLinker, err = newSiteRefLinker(s.Language, s) - if err != nil { - return err - } } return nil diff --git a/hugolib/page.go b/hugolib/page.go index f3e87be7d..4c48a6061 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -21,6 +21,8 @@ import ( "math/rand" "reflect" + "github.com/gohugoio/hugo/common/hugo" + "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/urls" "github.com/gohugoio/hugo/media" @@ -1873,8 +1875,8 @@ func (p *Page) copy(initContent bool) *Page { return &c } -func (p *Page) Hugo() *HugoInfo { - return hugoInfo +func (p *Page) Hugo() hugo.Info { + return p.s.Info.hugoInfo } // GetPage looks up a page for the given ref. diff --git a/hugolib/page_test.go b/hugolib/page_test.go index cd8bd8ffc..177ed7fb1 100644 --- a/hugolib/page_test.go +++ b/hugolib/page_test.go @@ -1436,7 +1436,7 @@ func TestIndexPageSimpleMethods(t *testing.T) { {func(n *Page) bool { return n.IsNode() }}, {func(n *Page) bool { return !n.IsPage() }}, {func(n *Page) bool { return n.Scratch() != nil }}, - {func(n *Page) bool { return n.Hugo() != nil }}, + {func(n *Page) bool { return n.Hugo().Version != "" }}, } { n := s.newHomePage() diff --git a/hugolib/pages_language_merge_test.go b/hugolib/pages_language_merge_test.go index 8a4688f16..6706af3bc 100644 --- a/hugolib/pages_language_merge_test.go +++ b/hugolib/pages_language_merge_test.go @@ -66,7 +66,7 @@ func TestMergeLanguages(t *testing.T) { firstNN := nnSite.RegularPages[0] assert.Equal(4, len(firstNN.Sites())) - assert.Equal("en", firstNN.Sites().First().Language.Lang) + assert.Equal("en", firstNN.Sites().First().Language().Lang) nnBundle := nnSite.getPage("page", "bundle") enBundle := enSite.getPage("page", "bundle") diff --git a/hugolib/site.go b/hugolib/site.go index 25eb34f05..d0e6c3018 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -36,11 +36,11 @@ import ( "github.com/gohugoio/hugo/common/herrors" - _errors "github.com/pkg/errors" - + "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/publisher" "github.com/gohugoio/hugo/resource" + _errors "github.com/pkg/errors" "github.com/gohugoio/hugo/langs" @@ -388,7 +388,7 @@ type SiteInfo struct { Social SiteSocial *PageCollections Menus *Menus - Hugo *HugoInfo + hugoInfo hugo.Info Title string RSSLink string Author map[string]interface{} @@ -405,17 +405,25 @@ type SiteInfo struct { Data *map[string]interface{} owner *HugoSites s *Site - Language *langs.Language + language *langs.Language LanguagePrefix string Languages langs.Languages defaultContentLanguageInSubdir bool sectionPagesMenu string } +func (s *SiteInfo) Language() *langs.Language { + return s.language +} + func (s *SiteInfo) Config() SiteConfig { return s.s.siteConfig } +func (s *SiteInfo) Hugo() hugo.Info { + return s.hugoInfo +} + func (s *SiteInfo) String() string { return fmt.Sprintf("Site(%q)", s.Title) } @@ -797,7 +805,10 @@ func (s *Site) processPartial(events []fsnotify.Event) (whatChanged, error) { MediaTypes: site.mediaTypesConfig, OutputFormats: site.outputFormatsConfig, } - site.Deps, err = first.Deps.ForLanguage(depsCfg) + site.Deps, err = first.Deps.ForLanguage(depsCfg, func(d *deps.Deps) error { + d.Site = &site.Info + return nil + }) if err != nil { return whatChanged{}, err } @@ -1122,7 +1133,7 @@ func (s *Site) initialize() (err error) { func (s *SiteInfo) HomeAbsURL() string { base := "" if s.IsMultiLingual() { - base = s.Language.Lang + base = s.Language().Lang } return s.owner.AbsURL(base, false) } @@ -1194,7 +1205,7 @@ func (s *Site) initializeSiteInfo() error { Social: lang.GetStringMapString("social"), LanguageCode: lang.GetString("languageCode"), Copyright: lang.GetString("copyright"), - Language: lang, + language: lang, LanguagePrefix: languagePrefix, Languages: languages, defaultContentLanguageInSubdir: defaultContentInSubDir, @@ -1211,6 +1222,7 @@ func (s *Site) initializeSiteInfo() error { Data: &s.Data, owner: s.owner, s: s, + hugoInfo: hugo.NewInfo(), // TODO(bep) make this Menu and similar into delegate methods on SiteInfo Taxonomies: s.Taxonomies, } diff --git a/hugolib/template_test.go b/hugolib/template_test.go index 9cc523cb0..32ede5639 100644 --- a/hugolib/template_test.go +++ b/hugolib/template_test.go @@ -236,3 +236,24 @@ Page Content b.AssertFileContent("public/page/index.html", "Base: Hi!?") } + +func TestTemplateFuncs(t *testing.T) { + + b := newTestSitesBuilder(t).WithDefaultMultiSiteConfig() + + homeTpl := `Site: {{ site.Language.Lang }} / {{ .Site.Language.Lang }} / {{ site.BaseURL }} +Hugo: {{ hugo.Generator }} +` + + b.WithTemplatesAdded( + "index.html", homeTpl, + "index.fr.html", homeTpl, + ) + + b.CreateSites().Build(BuildCfg{}) + + b.AssertFileContent("public/en/index.html", "Site: en / en / http://example.com/blog", + "Hugo: <meta name=\"generator\" content=\"Hugo") + b.AssertFileContent("public/fr/index.html", "Site: fr / fr / http://example.com/blog") + +} diff --git a/i18n/i18n_test.go b/i18n/i18n_test.go index 84b7384d0..5db539d30 100644 --- a/i18n/i18n_test.go +++ b/i18n/i18n_test.go @@ -20,6 +20,7 @@ import ( "github.com/gohugoio/hugo/tpl/tplimpl" "github.com/gohugoio/hugo/common/loggers" + "github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/langs" "github.com/spf13/afero" @@ -183,6 +184,7 @@ func newDepsConfig(tp *TranslationProvider, cfg config.Provider, fs *hugofs.Fs) l.Set("i18nDir", "i18n") return deps.DepsCfg{ Language: l, + Site: htesting.NewTestHugoSite(), Cfg: cfg, Fs: fs, Logger: logger, diff --git a/magefile.go b/magefile.go index e7ec106d7..cd873dd77 100644 --- a/magefile.go +++ b/magefile.go @@ -21,10 +21,10 @@ import ( const ( packageName = "github.com/gohugoio/hugo" - noGitLdflags = "-X $PACKAGE/hugolib.BuildDate=$BUILD_DATE" + noGitLdflags = "-X $PACKAGE/common/hugo.BuildDate=$BUILD_DATE" ) -var ldflags = "-X $PACKAGE/hugolib.CommitHash=$COMMIT_HASH -X $PACKAGE/hugolib.BuildDate=$BUILD_DATE" +var ldflags = "-X $PACKAGE/common/hugo.CommitHash=$COMMIT_HASH -X $PACKAGE/common/hugo.BuildDate=$BUILD_DATE" // allow user to override go executable by running as GOEXE=xxx make ... on unix-like systems var goexe = "go" diff --git a/releaser/releaser.go b/releaser/releaser.go index 0738fb81c..0c0765a71 100644 --- a/releaser/releaser.go +++ b/releaser/releaser.go @@ -25,9 +25,8 @@ import ( "regexp" "strings" + "github.com/gohugoio/hugo/common/hugo" "github.com/pkg/errors" - - "github.com/gohugoio/hugo/helpers" ) const commitPrefix = "releaser:" @@ -52,8 +51,8 @@ type ReleaseHandler struct { git func(args ...string) (string, error) } -func (r ReleaseHandler) calculateVersions() (helpers.HugoVersion, helpers.HugoVersion) { - newVersion := helpers.MustParseHugoVersion(r.cliVersion) +func (r ReleaseHandler) calculateVersions() (hugo.Version, hugo.Version) { + newVersion := hugo.MustParseVersion(r.cliVersion) finalVersion := newVersion.Next() finalVersion.PatchLevel = 0 @@ -261,14 +260,14 @@ func (r *ReleaseHandler) release(releaseNotesFile string) error { return nil } -func (r *ReleaseHandler) bumpVersions(ver helpers.HugoVersion) error { +func (r *ReleaseHandler) bumpVersions(ver hugo.Version) error { toDev := "" if ver.Suffix != "" { toDev = ver.Suffix } - if err := r.replaceInFile("helpers/hugo.go", + if err := r.replaceInFile("common/hugo/version_current.go", `Number:(\s{4,})(.*),`, fmt.Sprintf(`Number:${1}%.2f,`, ver.Number), `PatchLevel:(\s*)(.*),`, fmt.Sprintf(`PatchLevel:${1}%d,`, ver.PatchLevel), `Suffix:(\s{4,})".*",`, fmt.Sprintf(`Suffix:${1}"%s",`, toDev)); err != nil { diff --git a/tpl/compare/compare_test.go b/tpl/compare/compare_test.go index 61a84a629..d83680e53 100644 --- a/tpl/compare/compare_test.go +++ b/tpl/compare/compare_test.go @@ -21,8 +21,7 @@ import ( "testing" "time" - "github.com/gohugoio/hugo/helpers" - + "github.com/gohugoio/hugo/common/hugo" "github.com/spf13/cast" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -173,17 +172,17 @@ func doTestCompare(t *testing.T, tp tstCompareType, funcUnderTest func(a, b inte {tstEqerType1("a"), tstEqerType2("a"), 0}, {tstEqerType2("a"), tstEqerType1("a"), 0}, {tstEqerType2("a"), tstEqerType1("b"), -1}, - {helpers.MustParseHugoVersion("0.32.1").Version(), helpers.MustParseHugoVersion("0.32").Version(), 1}, - {helpers.MustParseHugoVersion("0.35").Version(), helpers.MustParseHugoVersion("0.32").Version(), 1}, - {helpers.MustParseHugoVersion("0.36").Version(), helpers.MustParseHugoVersion("0.36").Version(), 0}, - {helpers.MustParseHugoVersion("0.32").Version(), helpers.MustParseHugoVersion("0.36").Version(), -1}, - {helpers.MustParseHugoVersion("0.32").Version(), "0.36", -1}, - {"0.36", helpers.MustParseHugoVersion("0.32").Version(), 1}, - {"0.36", helpers.MustParseHugoVersion("0.36").Version(), 0}, - {"0.37", helpers.MustParseHugoVersion("0.37-DEV").Version(), 1}, - {"0.37-DEV", helpers.MustParseHugoVersion("0.37").Version(), -1}, - {"0.36", helpers.MustParseHugoVersion("0.37-DEV").Version(), -1}, - {"0.37-DEV", helpers.MustParseHugoVersion("0.37-DEV").Version(), 0}, + {hugo.MustParseVersion("0.32.1").Version(), hugo.MustParseVersion("0.32").Version(), 1}, + {hugo.MustParseVersion("0.35").Version(), hugo.MustParseVersion("0.32").Version(), 1}, + {hugo.MustParseVersion("0.36").Version(), hugo.MustParseVersion("0.36").Version(), 0}, + {hugo.MustParseVersion("0.32").Version(), hugo.MustParseVersion("0.36").Version(), -1}, + {hugo.MustParseVersion("0.32").Version(), "0.36", -1}, + {"0.36", hugo.MustParseVersion("0.32").Version(), 1}, + {"0.36", hugo.MustParseVersion("0.36").Version(), 0}, + {"0.37", hugo.MustParseVersion("0.37-DEV").Version(), 1}, + {"0.37-DEV", hugo.MustParseVersion("0.37").Version(), -1}, + {"0.36", hugo.MustParseVersion("0.37-DEV").Version(), -1}, + {"0.37-DEV", hugo.MustParseVersion("0.37-DEV").Version(), 0}, } { result := funcUnderTest(test.left, test.right) success := false diff --git a/tpl/hugo/init.go b/tpl/hugo/init.go new file mode 100644 index 000000000..5b6d5b99f --- /dev/null +++ b/tpl/hugo/init.go @@ -0,0 +1,41 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package site + +import ( + "github.com/gohugoio/hugo/deps" + "github.com/gohugoio/hugo/htesting" + "github.com/gohugoio/hugo/tpl/internal" +) + +const name = "hugo" + +func init() { + f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { + + h := htesting.NewTestHugoSite().Hugo() + + ns := &internal.TemplateFuncsNamespace{ + Name: name, + Context: func(args ...interface{}) interface{} { return h }, + } + + // We just add the Hugo struct as the namespace here. No method mappings. + + return ns + + } + + internal.AddTemplateFuncsNamespace(f) +} diff --git a/tpl/hugo/init_test.go b/tpl/hugo/init_test.go new file mode 100644 index 000000000..60612761b --- /dev/null +++ b/tpl/hugo/init_test.go @@ -0,0 +1,41 @@ +// Copyright 2017 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package site + +import ( + "testing" + + "github.com/gohugoio/hugo/htesting" + + "github.com/gohugoio/hugo/deps" + "github.com/gohugoio/hugo/tpl/internal" + "github.com/stretchr/testify/require" +) + +func TestInit(t *testing.T) { + var found bool + var ns *internal.TemplateFuncsNamespace + s := htesting.NewTestHugoSite() + + for _, nsf := range internal.TemplateFuncsNamespaceRegistry { + ns = nsf(&deps.Deps{Site: s}) + if ns.Name == name { + found = true + break + } + } + + require.True(t, found) + require.IsType(t, s.Hugo(), ns.Context()) +} diff --git a/tpl/site/init.go b/tpl/site/init.go new file mode 100644 index 000000000..4f5df0b0b --- /dev/null +++ b/tpl/site/init.go @@ -0,0 +1,44 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package site + +import ( + "github.com/gohugoio/hugo/deps" + + "github.com/gohugoio/hugo/tpl/internal" +) + +const name = "site" + +func init() { + f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { + + s := d.Site + ns := &internal.TemplateFuncsNamespace{ + Name: name, + Context: func(args ...interface{}) interface{} { return s }, + } + + if s == nil { + panic("no Site") + } + + // We just add the Site as the namespace here. No method mappings. + + return ns + + } + + internal.AddTemplateFuncsNamespace(f) +} diff --git a/tpl/site/init_test.go b/tpl/site/init_test.go new file mode 100644 index 000000000..00704d943 --- /dev/null +++ b/tpl/site/init_test.go @@ -0,0 +1,40 @@ +// Copyright 2017 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package site + +import ( + "testing" + + "github.com/gohugoio/hugo/deps" + "github.com/gohugoio/hugo/htesting" + "github.com/gohugoio/hugo/tpl/internal" + "github.com/stretchr/testify/require" +) + +func TestInit(t *testing.T) { + var found bool + var ns *internal.TemplateFuncsNamespace + s := htesting.NewTestHugoSite() + + for _, nsf := range internal.TemplateFuncsNamespaceRegistry { + ns = nsf(&deps.Deps{Site: s}) + if ns.Name == name { + found = true + break + } + } + + require.True(t, found) + require.IsType(t, s, ns.Context()) +} diff --git a/tpl/tplimpl/template_funcs.go b/tpl/tplimpl/template_funcs.go index 27ffcd97a..09bb9381a 100644 --- a/tpl/tplimpl/template_funcs.go +++ b/tpl/tplimpl/template_funcs.go @@ -30,6 +30,7 @@ import ( _ "github.com/gohugoio/hugo/tpl/data" _ "github.com/gohugoio/hugo/tpl/encoding" _ "github.com/gohugoio/hugo/tpl/fmt" + _ "github.com/gohugoio/hugo/tpl/hugo" _ "github.com/gohugoio/hugo/tpl/images" _ "github.com/gohugoio/hugo/tpl/inflect" _ "github.com/gohugoio/hugo/tpl/lang" @@ -39,6 +40,7 @@ import ( _ "github.com/gohugoio/hugo/tpl/path" _ "github.com/gohugoio/hugo/tpl/resources" _ "github.com/gohugoio/hugo/tpl/safe" + _ "github.com/gohugoio/hugo/tpl/site" _ "github.com/gohugoio/hugo/tpl/strings" _ "github.com/gohugoio/hugo/tpl/templates" _ "github.com/gohugoio/hugo/tpl/time" diff --git a/tpl/tplimpl/template_funcs_test.go b/tpl/tplimpl/template_funcs_test.go index 04bb4941a..22387dc01 100644 --- a/tpl/tplimpl/template_funcs_test.go +++ b/tpl/tplimpl/template_funcs_test.go @@ -21,10 +21,12 @@ import ( "testing" "time" + "github.com/gohugoio/hugo/htesting" + + "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/deps" - "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/i18n" "github.com/gohugoio/hugo/langs" @@ -57,6 +59,7 @@ func newDepsConfig(cfg config.Provider) deps.DepsCfg { l := langs.NewLanguage("en", cfg) return deps.DepsCfg{ Language: l, + Site: htesting.NewTestHugoSite(), Cfg: cfg, Fs: hugofs.NewMem(l), Logger: logger, @@ -98,7 +101,7 @@ func TestTemplateFuncsExamples(t *testing.T) { data.Title = "**BatMan**" data.Section = "blog" data.Params = map[string]interface{}{"langCode": "en"} - data.Hugo = map[string]interface{}{"Version": helpers.MustParseHugoVersion("0.36.1").Version()} + data.Hugo = map[string]interface{}{"Version": hugo.MustParseVersion("0.36.1").Version()} for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns := nsf(d) diff --git a/transform/metainject/hugogenerator.go b/transform/metainject/hugogenerator.go index 513b21228..5f3a8f63b 100644 --- a/transform/metainject/hugogenerator.go +++ b/transform/metainject/hugogenerator.go @@ -18,12 +18,13 @@ import ( "fmt" "regexp" + "github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/transform" ) var metaTagsCheck = regexp.MustCompile(`(?i)<meta\s+name=['|"]?generator['|"]?`) -var hugoGeneratorTag = fmt.Sprintf(`<meta name="generator" content="Hugo %s" />`, helpers.CurrentHugoVersion) +var hugoGeneratorTag = fmt.Sprintf(`<meta name="generator" content="Hugo %s" />`, hugo.CurrentVersion) // HugoGenerator injects a meta generator tag for Hugo if none present. func HugoGenerator(ft transform.FromTo) error { |