Add warnidf template function

Also rename config `ignoreErrors` => `ignoreLogs`

But the old still works.

Closes #9189
This commit is contained in:
Bjørn Erik Pedersen 2024-01-30 09:23:21 +01:00
parent f31a6db797
commit 4e84f57efb
11 changed files with 83 additions and 29 deletions

View file

@ -179,9 +179,9 @@ type Logger interface {
Debugln(v ...any) Debugln(v ...any)
Error() logg.LevelLogger Error() logg.LevelLogger
Errorf(format string, v ...any) Errorf(format string, v ...any)
Erroridf(id, format string, v ...any)
Errorln(v ...any) Errorln(v ...any)
Errors() string Errors() string
Errorsf(id, format string, v ...any)
Info() logg.LevelLogger Info() logg.LevelLogger
InfoCommand(command string) logg.LevelLogger InfoCommand(command string) logg.LevelLogger
Infof(format string, v ...any) Infof(format string, v ...any)
@ -197,6 +197,7 @@ type Logger interface {
Warn() logg.LevelLogger Warn() logg.LevelLogger
WarnCommand(command string) logg.LevelLogger WarnCommand(command string) logg.LevelLogger
Warnf(format string, v ...any) Warnf(format string, v ...any)
Warnidf(id, format string, v ...any)
Warnln(v ...any) Warnln(v ...any)
Deprecatef(fail bool, format string, v ...any) Deprecatef(fail bool, format string, v ...any)
Trace(s logg.StringFunc) Trace(s logg.StringFunc)
@ -321,10 +322,20 @@ func (l *logAdapter) Errors() string {
return l.errors.String() return l.errors.String()
} }
func (l *logAdapter) Errorsf(id, format string, v ...any) { func (l *logAdapter) Erroridf(id, format string, v ...any) {
format += l.idfInfoStatement("error", id, format)
l.errorl.WithField(FieldNameStatementID, id).Logf(format, v...) l.errorl.WithField(FieldNameStatementID, id).Logf(format, v...)
} }
func (l *logAdapter) Warnidf(id, format string, v ...any) {
format += l.idfInfoStatement("warning", id, format)
l.warnl.WithField(FieldNameStatementID, id).Logf(format, v...)
}
func (l *logAdapter) idfInfoStatement(what, id, format string) string {
return fmt.Sprintf("\nYou can suppress this %s by adding the following to your site configuration:\nignoreLogs = ['%s']", what, id)
}
func (l *logAdapter) Trace(s logg.StringFunc) { func (l *logAdapter) Trace(s logg.StringFunc) {
l.tracel.Log(s) l.tracel.Log(s)
} }

View file

@ -206,7 +206,7 @@ func (c Config) cloneForLang() *Config {
x.DisableKinds = copyStringSlice(x.DisableKinds) x.DisableKinds = copyStringSlice(x.DisableKinds)
x.DisableLanguages = copyStringSlice(x.DisableLanguages) x.DisableLanguages = copyStringSlice(x.DisableLanguages)
x.MainSections = copyStringSlice(x.MainSections) x.MainSections = copyStringSlice(x.MainSections)
x.IgnoreErrors = copyStringSlice(x.IgnoreErrors) x.IgnoreLogs = copyStringSlice(x.IgnoreLogs)
x.IgnoreFiles = copyStringSlice(x.IgnoreFiles) x.IgnoreFiles = copyStringSlice(x.IgnoreFiles)
x.Theme = copyStringSlice(x.Theme) x.Theme = copyStringSlice(x.Theme)
@ -299,9 +299,9 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
} }
} }
ignoredErrors := make(map[string]bool) ignoredLogIDs := make(map[string]bool)
for _, err := range c.IgnoreErrors { for _, err := range c.IgnoreLogs {
ignoredErrors[strings.ToLower(err)] = true ignoredLogIDs[strings.ToLower(err)] = true
} }
baseURL, err := urls.NewBaseURLFromString(c.BaseURL) baseURL, err := urls.NewBaseURLFromString(c.BaseURL)
@ -357,7 +357,7 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
BaseURLLiveReload: baseURL, BaseURLLiveReload: baseURL,
DisabledKinds: disabledKinds, DisabledKinds: disabledKinds,
DisabledLanguages: disabledLangs, DisabledLanguages: disabledLangs,
IgnoredErrors: ignoredErrors, IgnoredLogs: ignoredLogIDs,
KindOutputFormats: kindOutputFormats, KindOutputFormats: kindOutputFormats,
CreateTitle: helpers.GetTitleFunc(c.TitleCaseStyle), CreateTitle: helpers.GetTitleFunc(c.TitleCaseStyle),
IsUglyURLSection: isUglyURL, IsUglyURLSection: isUglyURL,
@ -394,7 +394,7 @@ type ConfigCompiled struct {
KindOutputFormats map[string]output.Formats KindOutputFormats map[string]output.Formats
DisabledKinds map[string]bool DisabledKinds map[string]bool
DisabledLanguages map[string]bool DisabledLanguages map[string]bool
IgnoredErrors map[string]bool IgnoredLogs map[string]bool
CreateTitle func(s string) string CreateTitle func(s string) string
IsUglyURLSection func(section string) bool IsUglyURLSection func(section string) bool
IgnoreFile func(filename string) bool IgnoreFile func(filename string) bool
@ -501,8 +501,8 @@ type RootConfig struct {
// Enable to disable the build lock file. // Enable to disable the build lock file.
NoBuildLock bool NoBuildLock bool
// A list of error IDs to ignore. // A list of log IDs to ignore.
IgnoreErrors []string IgnoreLogs []string
// A list of regexps that match paths to ignore. // A list of regexps that match paths to ignore.
// Deprecated: Use the settings on module imports. // Deprecated: Use the settings on module imports.

View file

@ -89,8 +89,8 @@ func (c ConfigLanguage) IsLangDisabled(lang string) bool {
return c.config.C.DisabledLanguages[lang] return c.config.C.DisabledLanguages[lang]
} }
func (c ConfigLanguage) IgnoredErrors() map[string]bool { func (c ConfigLanguage) IgnoredLogs() map[string]bool {
return c.config.C.IgnoredErrors return c.config.C.IgnoredLogs
} }
func (c ConfigLanguage) NoBuildLock() bool { func (c ConfigLanguage) NoBuildLock() bool {

View file

@ -141,6 +141,7 @@ func (l configLoader) applyConfigAliases() error {
{Key: "indexes", Value: "taxonomies"}, {Key: "indexes", Value: "taxonomies"},
{Key: "logI18nWarnings", Value: "printI18nWarnings"}, {Key: "logI18nWarnings", Value: "printI18nWarnings"},
{Key: "logPathWarnings", Value: "printPathWarnings"}, {Key: "logPathWarnings", Value: "printPathWarnings"},
{Key: "ignoreErrors", Value: "ignoreLogs"},
} }
for _, alias := range aliases { for _, alias := range aliases {

View file

@ -67,7 +67,7 @@ type AllProvider interface {
NewContentEditor() string NewContentEditor() string
Timeout() time.Duration Timeout() time.Duration
StaticDirs() []string StaticDirs() []string
IgnoredErrors() map[string]bool IgnoredLogs() map[string]bool
WorkingDir() string WorkingDir() string
EnableEmoji() bool EnableEmoji() bool
} }

View file

@ -57,6 +57,13 @@ func TestOptDebug() TestOpt {
} }
} }
// TestOptWarn will enable warn logging in integration tests.
func TestOptWarn() TestOpt {
return func(c *IntegrationTestConfig) {
c.LogLevel = logg.LevelWarn
}
}
// TestOptWithNFDOnDarwin will normalize the Unicode filenames to NFD on Darwin. // TestOptWithNFDOnDarwin will normalize the Unicode filenames to NFD on Darwin.
func TestOptWithNFDOnDarwin() TestOpt { func TestOptWithNFDOnDarwin() TestOpt {
return func(c *IntegrationTestConfig) { return func(c *IntegrationTestConfig) {
@ -181,9 +188,18 @@ func (b *lockingBuffer) Write(p []byte) (n int, err error) {
return return
} }
func (s *IntegrationTestBuilder) AssertLogContains(text string) { func (s *IntegrationTestBuilder) AssertLogContains(els ...string) {
s.Helper() s.Helper()
s.Assert(s.logBuff.String(), qt.Contains, text) for _, el := range els {
s.Assert(s.logBuff.String(), qt.Contains, el)
}
}
func (s *IntegrationTestBuilder) AssertLogNotContains(els ...string) {
s.Helper()
for _, el := range els {
s.Assert(s.logBuff.String(), qt.Not(qt.Contains), el)
}
} }
func (s *IntegrationTestBuilder) AssertLogMatches(expression string) { func (s *IntegrationTestBuilder) AssertLogMatches(expression string) {

View file

@ -124,7 +124,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
Stdout: cfg.LogOut, Stdout: cfg.LogOut,
Stderr: cfg.LogOut, Stderr: cfg.LogOut,
StoreErrors: conf.Running(), StoreErrors: conf.Running(),
SuppressStatements: conf.IgnoredErrors(), SuppressStatements: conf.IgnoredLogs(),
} }
logger = loggers.New(logOpts) logger = loggers.New(logOpts)
} }

View file

@ -94,7 +94,7 @@ func (ns *Namespace) GetCSV(sep string, args ...any) (d [][]string, err error) {
if security.IsAccessDenied(err) { if security.IsAccessDenied(err) {
return nil, err return nil, err
} }
ns.deps.Log.Errorsf(constants.ErrRemoteGetCSV, "Failed to get CSV resource %q: %s", url, err) ns.deps.Log.Erroridf(constants.ErrRemoteGetCSV, "Failed to get CSV resource %q: %s", url, err)
return nil, nil return nil, nil
} }
@ -132,7 +132,7 @@ func (ns *Namespace) GetJSON(args ...any) (any, error) {
if security.IsAccessDenied(err) { if security.IsAccessDenied(err) {
return nil, err return nil, err
} }
ns.deps.Log.Errorsf(constants.ErrRemoteGetJSON, "Failed to get JSON resource %q: %s", url, err) ns.deps.Log.Erroridf(constants.ErrRemoteGetJSON, "Failed to get JSON resource %q: %s", url, err)
return nil, nil return nil, nil
} }

View file

@ -68,9 +68,7 @@ func (ns *Namespace) Errorf(format string, args ...any) string {
// an information text that the error with the given id can be suppressed in config. // an information text that the error with the given id can be suppressed in config.
// It returns an empty string. // It returns an empty string.
func (ns *Namespace) Erroridf(id, format string, args ...any) string { func (ns *Namespace) Erroridf(id, format string, args ...any) string {
format += "\nYou can suppress this error by adding the following to your site configuration:\nignoreErrors = ['%s']" ns.logger.Erroridf(id, format, args...)
args = append(args, id)
ns.logger.Errorsf(id, format, args...)
return "" return ""
} }
@ -81,6 +79,14 @@ func (ns *Namespace) Warnf(format string, args ...any) string {
return "" return ""
} }
// Warnidf formats args according to a format specifier and logs an WARNING and
// an information text that the warning with the given id can be suppressed in config.
// It returns an empty string.
func (ns *Namespace) Warnidf(id, format string, args ...any) string {
ns.logger.Warnidf(id, format, args...)
return ""
}
// Warnmf is epxermimental and subject to change at any time. // Warnmf is epxermimental and subject to change at any time.
func (ns *Namespace) Warnmf(m any, format string, args ...any) string { func (ns *Namespace) Warnmf(m any, format string, args ...any) string {
return ns.logmf(ns.logger.Warn(), m, format, args...) return ns.logmf(ns.logger.Warn(), m, format, args...)

View file

@ -16,6 +16,7 @@ package fmt_test
import ( import (
"testing" "testing"
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/hugolib"
) )
@ -32,13 +33,25 @@ ignoreErrors = ['error-b']
{{ erroridf "error-b" "%s" "b"}} {{ erroridf "error-b" "%s" "b"}}
` `
b := hugolib.NewIntegrationTestBuilder( b, err := hugolib.TestE(t, files)
hugolib.IntegrationTestConfig{
T: t,
TxtarString: files,
},
)
b.BuildE() b.Assert(err, qt.IsNotNil)
b.AssertLogMatches(`^ERROR a\nYou can suppress this error by adding the following to your site configuration:\nignoreErrors = \['error-a'\]\n$`) b.AssertLogMatches(`^ERROR a\nYou can suppress this error by adding the following to your site configuration:\nignoreLogs = \['error-a'\]\n$`)
}
func TestWarnidf(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
ignoreLogs = ['warning-b']
-- layouts/index.html --
{{ warnidf "warning-a" "%s" "a"}}
{{ warnidf "warning-b" "%s" "b"}}
`
b := hugolib.Test(t, files, hugolib.TestOptWarn())
b.AssertLogContains("WARN a", "You can suppress this warning", "ignoreLogs", "['warning-a']")
b.AssertLogNotContains("['warning-b']")
} }

View file

@ -66,6 +66,13 @@ func init() {
}, },
) )
ns.AddMethodMapping(ctx.Warnidf,
[]string{"warnidf"},
[][2]string{
{`{{ warnidf "my-warn-id" "%s." "warning" }}`, ``},
},
)
ns.AddMethodMapping(ctx.Warnf, ns.AddMethodMapping(ctx.Warnf,
[]string{"warnf"}, []string{"warnf"},
[][2]string{ [][2]string{