This introduces a more automatic way of increasing the log levels for deprecation log statements based on the version it was deprecated.
The thresholds are a little arbitrary, but
* We log INFO for 6 releases
* We log WARN for another 6 releases
* THen ERROR (failing the build)
This should give theme authors plenty of time to catch up without having the log filled with warnings.
"github.com/gohugoio/hugo/common/hstrings"
"github.com/gohugoio/hugo/common/htime"
+ "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/config"
"github.com/spf13/cobra"
)
-var (
- errHelp = errors.New("help requested")
-)
+var errHelp = errors.New("help requested")
// Execute executes a command.
func Execute(args []string) error {
cfg: oldConf.cfg,
fs: fs,
}, nil
-
})
return cc, err
-
}
func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commonConfig, error) {
if !cfg.IsSet("workingDir") {
cfg.Set("workingDir", dir)
} else {
- if err := os.MkdirAll(cfg.GetString("workingDir"), 0777); err != nil {
+ if err := os.MkdirAll(cfg.GetString("workingDir"), 0o777); err != nil {
return nil, fmt.Errorf("failed to create workingDir: %w", err)
}
}
})
return cc, err
-
}
func (r *rootCommand) HugFromConfig(conf *commonConfig) (*hugolib.HugoSites, error) {
err := b.build()
return err
}()
-
if err != nil {
return err
}
}
} else {
if r.verbose {
- helpers.Deprecated("--verbose", "use --logLevel info", false)
+ hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
+ hugo.Deprecate("--verbose", "use --logLevel info", "v0.114.0")
level = logg.LevelInfo
}
if r.debug {
- helpers.Deprecated("--debug", "use --logLevel debug", false)
+ hugo.Deprecate("--debug", "use --logLevel debug", "v0.114.0")
level = logg.LevelDebug
}
}
}
return loggers.New(optsLogger), nil
-
}
func (r *rootCommand) Reset() {
_ = cmd.Flags().SetAnnotation("cacheDir", cobra.BashCompSubdirsInDir, []string{})
cmd.Flags().StringP("contentDir", "c", "", "filesystem path to content directory")
_ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"})
-
}
// Flags needed to do a build (used by hugo and hugo server commands)
cmd.Flags().StringSlice("disableKinds", []string{}, "disable different kind of pages (home, RSS etc.)")
cmd.Flags().Bool("minify", false, "minify any supported output format (HTML, XML etc.)")
_ = cmd.Flags().SetAnnotation("destination", cobra.BashCompSubdirsInDir, []string{})
-
}
func (r *rootCommand) timeTrack(start time.Time, name string) {
"sort"
"strings"
"sync"
+ "time"
godartsassv1 "github.com/bep/godartsass"
+ "github.com/bep/logg"
"github.com/mitchellh/mapstructure"
- "time"
-
"github.com/bep/godartsass/v2"
"github.com/gohugoio/hugo/common/hexec"
+ "github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/hugofs/files"
"github.com/spf13/afero"
*debug.BuildInfo
}
-var bInfo *buildInfo
-var bInfoInit sync.Once
+var (
+ bInfo *buildInfo
+ bInfoInit sync.Once
+)
func getBuildInfo() *buildInfo {
bInfoInit.Do(func() {
bInfo.GoArch = s.Value
}
}
-
})
return bInfo
}
if dartSass := dartSassVersion(); dartSass.ProtocolVersion != "" {
- var dartSassPath = "github.com/sass/dart-sass-embedded"
+ dartSassPath := "github.com/sass/dart-sass-embedded"
if IsDartSassV2() {
dartSassPath = "github.com/sass/dart-sass"
}
func IsDartSassV2() bool {
return !strings.Contains(DartSassBinaryName, "embedded")
}
+
+// Deprecate informs about a deprecation starting at the given version.
+//
+// A deprecation typically needs a simple change in the template, but doing so will make the template incompatible with older versions.
+// Theme maintainers generally want
+// 1. No warnings or errors in the console when building a Hugo site.
+// 2. Their theme to work for at least the last few Hugo versions.
+func Deprecate(item, alternative string, version string) {
+ level := deprecationLogLevelFromVersion(version)
+ DeprecateLevel(item, alternative, version, level)
+}
+
+// DeprecateLevel informs about a deprecation logging at the given level.
+func DeprecateLevel(item, alternative, version string, level logg.Level) {
+ var msg string
+ if level == logg.LevelError {
+ msg = fmt.Sprintf("%s was deprecated in Hugo %s and will be removed in Hugo %s. %s", item, version, CurrentVersion.Next().ReleaseVersion(), alternative)
+ } else {
+ msg = fmt.Sprintf("%s was deprecated in Hugo %s and will be removed in a future release. %s", item, version, alternative)
+ }
+
+ loggers.Log().Logger().WithLevel(level).Logf(msg)
+}
+
+// We ususally do about one minor version a month.
+// We want people to run at least the current and previous version without any warnings.
+// We want people who don't update Hugo that often to see the warnings and errors before we remove the feature.
+func deprecationLogLevelFromVersion(ver string) logg.Level {
+ from := MustParseVersion(ver)
+ to := CurrentVersion
+ minorDiff := to.Minor - from.Minor
+ switch {
+ case minorDiff >= 12:
+ // Start failing the build after about a year.
+ return logg.LevelError
+ case minorDiff >= 6:
+ // Start printing warnings after about six months.
+ return logg.LevelWarn
+ default:
+ return logg.LevelInfo
+ }
+}
"fmt"
"testing"
+ "github.com/bep/logg"
qt "github.com/frankban/quicktest"
)
c.Assert(devHugoInfo.IsServer(), qt.Equals, true)
}
+func TestDeprecationLogLevelFromVersion(t *testing.T) {
+ c := qt.New(t)
+
+ c.Assert(deprecationLogLevelFromVersion("0.55.0"), qt.Equals, logg.LevelError)
+ ver := CurrentVersion
+ c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelInfo)
+ ver.Minor -= 1
+ c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelInfo)
+ ver.Minor -= 6
+ c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelWarn)
+ ver.Minor -= 6
+ c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelError)
+}
+
type testConfig struct {
environment string
running bool
// Compare implements the compare.Comparer interface.
func (h VersionString) Compare(other any) int {
- v := MustParseVersion(h.String())
- return compareVersions(v, other)
+ return compareVersions(h.Version(), other)
+}
+
+func (h VersionString) Version() Version {
+ return MustParseVersion(h.String())
}
// Eq implements the compare.Eqer interface.
if v1maj > v2.Major {
return 1
-
}
if v1maj < v2.Major {
}
return -1
-
}
func GoMinorVersion() int {
"time"
"github.com/gohugoio/hugo/cache/filecache"
+ "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/urls"
// We accidentally allowed it in the past, so we need to support it a little longer,
// But log a warning.
if _, found := params[kk]; !found {
- helpers.Deprecated(fmt.Sprintf("config: languages.%s.%s: custom params on the language top level", k, kk), fmt.Sprintf("Put the value below [languages.%s.params]. See https://gohugo.io/content-management/multilingual/#changes-in-hugo-01120", k), false)
+ hugo.Deprecate(fmt.Sprintf("config: languages.%s.%s: custom params on the language top level", k, kk), fmt.Sprintf("Put the value below [languages.%s.params]. See https://gohugo.io/content-management/multilingual/#changes-in-hugo-01120", k), "v0.112.0")
params[kk] = vv
}
}
"unicode"
"unicode/utf8"
- "github.com/gohugoio/hugo/common/hugo"
- "github.com/gohugoio/hugo/common/loggers"
-
"github.com/spf13/afero"
"github.com/jdkato/prose/transform"
return true
}
-// Deprecated informs about a deprecation, but only once for a given set of arguments' values.
-// If the err flag is enabled, it logs as an ERROR (will exit with -1) and the text will
-// point at the next Hugo release.
-// The idea is two remove an item in two Hugo releases to give users and theme authors
-// plenty of time to fix their templates.
-func Deprecated(item, alternative string, err bool) {
- if err {
- loggers.Log().Errorf("%s is deprecated and will be removed in Hugo %s. %s", item, hugo.CurrentVersion.Next().ReleaseVersion(), alternative)
- } else {
- loggers.Log().Warnf("%s is deprecated and will be removed in a future release. %s", item, alternative)
- }
-}
-
// SliceToLower goes through the source slice and lowers all values.
func SliceToLower(s []string) []string {
if s == nil {
"github.com/bep/logg"
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/publisher"
"github.com/gohugoio/hugo/tpl"
"github.com/gohugoio/hugo/output"
"github.com/fsnotify/fsnotify"
- "github.com/gohugoio/hugo/helpers"
)
-func init() {
- // To avoid circular dependencies, we set this here.
- langs.DeprecationFunc = helpers.Deprecated
-}
-
// Build builds all sites. If filesystem events are provided,
// this is considered to be a potential partial rebuild.
func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
}
func (p *pageMeta) Author() page.Author {
- helpers.Deprecated(".Author", "Use taxonomies.", false)
+ hugo.Deprecate(".Author", "Use taxonomies.", "v0.98.0")
authors := p.Authors()
for _, author := range authors {
}
func (p *pageMeta) Authors() page.AuthorList {
- helpers.Deprecated(".Authors", "Use taxonomies.", true)
+ hugo.Deprecate(".Author", "Use taxonomies.", "v0.112.0")
return nil
}
{{ $path = .Path }}
{{ end }}
`
- helpers.Deprecated(".Path when the page is backed by a file", "We plan to use Path for a canonical source path and you probably want to check the source is a file. To get the current behaviour, you can use a construct similar to the one below:\n"+example, false)
+ p.s.Log.Warnln(".Path when the page is backed by a file is deprecated. We plan to use Path for a canonical source path and you probably want to check the source is a file. To get the current behaviour, you can use a construct similar to the one below:\n" + example)
}
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/config/allconfig"
"github.com/gohugoio/hugo/deps"
- "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/identity"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/langs/i18n"
"github.com/gohugoio/hugo/tpl/tplimpl"
)
-var (
- _ page.Site = (*Site)(nil)
-)
+var _ page.Site = (*Site)(nil)
type Site struct {
conf *allconfig.Config
}
return h, err
-
}
func newHugoSitesNew(cfg deps.DepsCfg, d *deps.Deps, sites []*Site) (*HugoSites, error) {
// Returns true if we're running in a server.
// Deprecated: use hugo.IsServer instead
func (s *Site) IsServer() bool {
- helpers.Deprecated(".Site.IsServer", "Use hugo.IsServer instead.", false)
+ hugo.Deprecate(".Site.IsServer", "Use hugo.IsServer instead.", "v0.120.0")
return s.conf.Internal.Running
}
}
func (s *Site) RSSLink() template.URL {
- helpers.Deprecated("Site.RSSLink", "Use the Output Format's Permalink method instead, e.g. .OutputFormats.Get \"RSS\".Permalink", false)
+ hugo.Deprecate("Site.RSSLink", "Use the Output Format's Permalink method instead, e.g. .OutputFormats.Get \"RSS\".Permalink", "v0.114.0")
rssOutputFormat := s.home.OutputFormats().Get("rss")
return template.URL(rssOutputFormat.Permalink())
}
// Deprecated: Use .Site.Config.Services.Disqus.Shortname instead
func (s *Site) DisqusShortname() string {
- helpers.Deprecated(".Site.DisqusShortname", "Use .Site.Config.Services.Disqus.Shortname instead.", false)
+ hugo.Deprecate(".Site.DisqusShortname", "Use .Site.Config.Services.Disqus.Shortname instead.", "v0.120.0")
return s.Config().Services.Disqus.Shortname
}
// Deprecated: Use .Site.Config.Services.GoogleAnalytics.ID instead
func (s *Site) GoogleAnalytics() string {
- helpers.Deprecated(".Site.GoogleAnalytics", "Use .Site.Config.Services.GoogleAnalytics.ID instead.", false)
+ hugo.Deprecate(".Site.GoogleAnalytics", "Use .Site.Config.Services.GoogleAnalytics.ID instead.", "v0.120.0")
return s.Config().Services.GoogleAnalytics.ID
}
"time"
"github.com/bep/gitmap"
+ "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/hugofs/files"
}
type FileWithoutOverlap interface {
-
// Filename gets the full path and filename to the file.
Filename() string
// FileInfo describes a source file.
type FileInfo struct {
-
// Absolute filename to the file on disk.
filename string
// Extension is an alias to Ext().
func (fi *FileInfo) Extension() string {
- helpers.Deprecated(".File.Extension", "Use .File.Ext instead. ", false)
+ hugo.Deprecate(".File.Extension", "Use .File.Ext instead.", "v0.96.0")
return fi.Ext()
}
"errors"
"github.com/gohugoio/hugo/common/collections"
+ "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/deps"
- "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/tpl/compare"
"github.com/spf13/cast"
// empty string.
// Deprecated: Use the index function instead.
func (ns *Namespace) EchoParam(c, k any) any {
- helpers.Deprecated("collections.EchoParam", "Use the index function instead.", false)
+ hugo.Deprecate("collections.EchoParam", "Use the index function instead.", "v0.120.0")
av, isNil := indirect(reflect.ValueOf(c))
if isNil {
return ""
import (
"context"
+ "errors"
"fmt"
"math"
"strconv"
"strings"
- "errors"
-
"github.com/gohugoio/locales"
translators "github.com/gohugoio/localescompressed"
"github.com/gohugoio/hugo/common/hreflect"
+ "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/deps"
- "github.com/gohugoio/hugo/helpers"
"github.com/spf13/cast"
)
// Deprecated: Use lang.FormatNumberCustom instead.
func (ns *Namespace) NumFmt(precision, number any, options ...any) (string, error) {
- helpers.Deprecated("lang.NumFmt", "Use lang.FormatNumberCustom instead.", false)
+ hugo.Deprecate("lang.NumFmt", "Use lang.FormatNumberCustom instead.", "v0.120.0")
return ns.FormatNumberCustom(precision, number, options...)
}