mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-14 20:37:55 -05:00
parent
0e79446586
commit
7c9fada778
80 changed files with 1273 additions and 1082 deletions
5
cache/filecache/integration_test.go
vendored
5
cache/filecache/integration_test.go
vendored
|
@ -16,11 +16,10 @@ package filecache_test
|
|||
import (
|
||||
"path/filepath"
|
||||
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bep/logg"
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/htesting"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
|
@ -80,7 +79,7 @@ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAA
|
|||
`
|
||||
|
||||
b := hugolib.NewIntegrationTestBuilder(
|
||||
hugolib.IntegrationTestConfig{T: t, TxtarString: files, Running: true, RunGC: true, NeedsOsFS: true, LogLevel: jww.LevelInfo},
|
||||
hugolib.IntegrationTestConfig{T: t, TxtarString: files, Running: true, RunGC: true, NeedsOsFS: true, LogLevel: logg.LevelInfo},
|
||||
).Build()
|
||||
|
||||
b.Assert(b.GCCount, qt.Equals, 0)
|
||||
|
|
|
@ -28,12 +28,11 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
|
||||
"go.uber.org/automaxprocs/maxprocs"
|
||||
|
||||
"github.com/bep/clock"
|
||||
"github.com/bep/lazycache"
|
||||
"github.com/bep/logg"
|
||||
"github.com/bep/overlayfs"
|
||||
"github.com/bep/simplecobra"
|
||||
|
||||
|
@ -114,7 +113,6 @@ type rootCommand struct {
|
|||
baseURL string
|
||||
gc bool
|
||||
poll string
|
||||
panicOnWarning bool
|
||||
forceSyncStatic bool
|
||||
printPathWarnings bool
|
||||
printUnusedTemplates bool
|
||||
|
@ -308,7 +306,7 @@ func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commo
|
|||
|
||||
func (r *rootCommand) HugFromConfig(conf *commonConfig) (*hugolib.HugoSites, error) {
|
||||
h, _, err := r.hugoSites.GetOrCreate(r.configVersionID.Load(), func(key int32) (*hugolib.HugoSites, error) {
|
||||
depsCfg := deps.DepsCfg{Configs: conf.configs, Fs: conf.fs, Logger: r.logger}
|
||||
depsCfg := deps.DepsCfg{Configs: conf.configs, Fs: conf.fs, LogOut: r.logger.Out(), LogLevel: r.logger.Level()}
|
||||
return hugolib.NewHugoSites(depsCfg)
|
||||
})
|
||||
return h, err
|
||||
|
@ -320,7 +318,7 @@ func (r *rootCommand) Hugo(cfg config.Provider) (*hugolib.HugoSites, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
depsCfg := deps.DepsCfg{Configs: conf.configs, Fs: conf.fs, Logger: r.logger}
|
||||
depsCfg := deps.DepsCfg{Configs: conf.configs, Fs: conf.fs, LogOut: r.logger.Out(), LogLevel: r.logger.Level()}
|
||||
return hugolib.NewHugoSites(depsCfg)
|
||||
})
|
||||
return h, err
|
||||
|
@ -410,7 +408,6 @@ func (r *rootCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
|
|||
return err
|
||||
}
|
||||
|
||||
loggers.PanicOnWarning.Store(r.panicOnWarning)
|
||||
r.commonConfigs = lazycache.New[int32, *commonConfig](lazycache.Options{MaxEntries: 5})
|
||||
r.hugoSites = lazycache.New[int32, *hugolib.HugoSites](lazycache.Options{MaxEntries: 5})
|
||||
|
||||
|
@ -418,43 +415,48 @@ func (r *rootCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
|
|||
}
|
||||
|
||||
func (r *rootCommand) createLogger(running bool) (loggers.Logger, error) {
|
||||
var (
|
||||
outHandle = r.Out
|
||||
stdoutThreshold = jww.LevelWarn
|
||||
)
|
||||
|
||||
if r.verbose {
|
||||
helpers.Deprecated("--verbose", "use --logLevel info", false)
|
||||
stdoutThreshold = jww.LevelInfo
|
||||
}
|
||||
|
||||
if r.debug {
|
||||
helpers.Deprecated("--debug", "use --logLevel debug", false)
|
||||
stdoutThreshold = jww.LevelDebug
|
||||
}
|
||||
level := logg.LevelWarn
|
||||
|
||||
if r.logLevel != "" {
|
||||
switch strings.ToLower(r.logLevel) {
|
||||
case "debug":
|
||||
stdoutThreshold = jww.LevelDebug
|
||||
level = logg.LevelDebug
|
||||
case "info":
|
||||
stdoutThreshold = jww.LevelInfo
|
||||
level = logg.LevelInfo
|
||||
case "warn", "warning":
|
||||
stdoutThreshold = jww.LevelWarn
|
||||
level = logg.LevelWarn
|
||||
case "error":
|
||||
stdoutThreshold = jww.LevelError
|
||||
level = logg.LevelError
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid log level: %q, must be one of debug, warn, info or error", r.logLevel)
|
||||
}
|
||||
} else {
|
||||
if r.verbose {
|
||||
helpers.Deprecated("--verbose", "use --logLevel info", false)
|
||||
level = logg.LevelInfo
|
||||
}
|
||||
|
||||
if r.debug {
|
||||
helpers.Deprecated("--debug", "use --logLevel debug", false)
|
||||
level = logg.LevelDebug
|
||||
}
|
||||
}
|
||||
|
||||
loggers.InitGlobalLogger(stdoutThreshold, jww.LevelWarn, outHandle, io.Discard)
|
||||
helpers.InitLoggers()
|
||||
return loggers.NewLogger(stdoutThreshold, jww.LevelWarn, outHandle, io.Discard, running), nil
|
||||
optsLogger := loggers.Options{
|
||||
Distinct: true,
|
||||
Level: level,
|
||||
Stdout: r.Out,
|
||||
Stderr: r.Out,
|
||||
StoreErrors: running,
|
||||
}
|
||||
|
||||
return loggers.New(optsLogger), nil
|
||||
|
||||
}
|
||||
|
||||
func (r *rootCommand) Reset() {
|
||||
r.logger.Reset()
|
||||
loggers.Log().Reset()
|
||||
}
|
||||
|
||||
// IsTestRun reports whether the command is running as a test.
|
||||
|
@ -530,7 +532,7 @@ func applyLocalFlagsBuild(cmd *cobra.Command, r *rootCommand) {
|
|||
cmd.Flags().StringP("layoutDir", "l", "", "filesystem path to layout directory")
|
||||
cmd.Flags().BoolVar(&r.gc, "gc", false, "enable to run some cleanup tasks (remove unused cache files) after the build")
|
||||
cmd.Flags().StringVar(&r.poll, "poll", "", "set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes")
|
||||
cmd.Flags().BoolVar(&r.panicOnWarning, "panicOnWarning", false, "panic on first WARNING log")
|
||||
cmd.Flags().Bool("panicOnWarning", false, "panic on first WARNING log")
|
||||
cmd.Flags().Bool("templateMetrics", false, "display metrics about template executions")
|
||||
cmd.Flags().Bool("templateMetricsHints", false, "calculate some improvement hints when combined with --templateMetrics")
|
||||
cmd.Flags().BoolVar(&r.forceSyncStatic, "forceSyncStatic", false, "copy all files when static is changed.")
|
||||
|
|
|
@ -52,7 +52,7 @@ documentation.
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
deployer, err := deploy.New(h.Configs.GetFirstLanguageConfig(), h.PathSpec.PublishFs)
|
||||
deployer, err := deploy.New(h.Configs.GetFirstLanguageConfig(), h.Log, h.PathSpec.PublishFs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -26,11 +26,13 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/bep/simplecobra"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
"github.com/gohugoio/hugo/common/htime"
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/common/terminal"
|
||||
"github.com/gohugoio/hugo/common/types"
|
||||
|
@ -68,7 +70,6 @@ type hugoBuilder struct {
|
|||
onConfigLoaded func(reloaded bool) error
|
||||
|
||||
fastRenderMode bool
|
||||
buildWatch bool
|
||||
showErrorInBrowser bool
|
||||
|
||||
errState hugoBuilderErrState
|
||||
|
@ -131,7 +132,7 @@ func (e *hugoBuilderErrState) wasErr() bool {
|
|||
}
|
||||
|
||||
func (c *hugoBuilder) errCount() int {
|
||||
return int(c.r.logger.LogCounters().ErrorCounter.Count())
|
||||
return c.r.logger.LoggCount(logg.LevelError) + loggers.Log().LoggCount(logg.LevelError)
|
||||
}
|
||||
|
||||
// getDirList provides NewWatcher() with a list of directories to watch for changes.
|
||||
|
@ -363,7 +364,7 @@ func (c *hugoBuilder) newWatcher(pollIntervalStr string, dirList ...string) (*wa
|
|||
configFiles = conf.configs.LoadingInfo.ConfigFiles
|
||||
})
|
||||
|
||||
c.r.logger.Println("Watching for config changes in", strings.Join(configFiles, ", "))
|
||||
c.r.Println("Watching for config changes in", strings.Join(configFiles, ", "))
|
||||
for _, configFile := range configFiles {
|
||||
watcher.Add(configFile)
|
||||
configSet[configFile] = true
|
||||
|
@ -461,6 +462,7 @@ func (c *hugoBuilder) copyStatic() (map[string]uint64, error) {
|
|||
}
|
||||
|
||||
func (c *hugoBuilder) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint64, error) {
|
||||
infol := c.r.logger.InfoCommand("copy static")
|
||||
publishDir := helpers.FilePathSeparator
|
||||
|
||||
if sourceFs.PublishFolder != "" {
|
||||
|
@ -484,13 +486,13 @@ func (c *hugoBuilder) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint
|
|||
syncer.SrcFs = fs
|
||||
|
||||
if syncer.Delete {
|
||||
c.r.logger.Infoln("removing all files from destination that don't exist in static dirs")
|
||||
infol.Logf("removing all files from destination that don't exist in static dirs")
|
||||
|
||||
syncer.DeleteFilter = func(f os.FileInfo) bool {
|
||||
return f.IsDir() && strings.HasPrefix(f.Name(), ".")
|
||||
}
|
||||
}
|
||||
c.r.logger.Infoln("syncing static files to", publishDir)
|
||||
infol.Logf("syncing static files to %s", publishDir)
|
||||
|
||||
// because we are using a baseFs (to get the union right).
|
||||
// set sync src to root
|
||||
|
@ -545,14 +547,13 @@ func (c *hugoBuilder) fullBuild(noBuildLock bool) error {
|
|||
langCount map[string]uint64
|
||||
)
|
||||
|
||||
if !c.r.quiet {
|
||||
fmt.Println("Start building sites … ")
|
||||
fmt.Println(hugo.BuildVersionString())
|
||||
if terminal.IsTerminal(os.Stdout) {
|
||||
defer func() {
|
||||
fmt.Print(showCursor + clearLine)
|
||||
}()
|
||||
}
|
||||
c.r.logger.Println("Start building sites … ")
|
||||
c.r.logger.Println(hugo.BuildVersionString())
|
||||
c.r.logger.Println()
|
||||
if terminal.IsTerminal(os.Stdout) {
|
||||
defer func() {
|
||||
fmt.Print(showCursor + clearLine)
|
||||
}()
|
||||
}
|
||||
|
||||
copyStaticFunc := func() error {
|
||||
|
|
|
@ -19,12 +19,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -299,7 +298,7 @@ func (c *importCommand) convertJekyllMetaData(m any, postName string, postDate t
|
|||
}
|
||||
|
||||
func (c *importCommand) convertJekyllPost(path, relPath, targetDir string, draft bool) error {
|
||||
jww.TRACE.Println("Converting", path)
|
||||
log.Println("Converting", path)
|
||||
|
||||
filename := filepath.Base(path)
|
||||
postDate, postName, err := c.parseJekyllFilename(filename)
|
||||
|
@ -308,7 +307,7 @@ func (c *importCommand) convertJekyllPost(path, relPath, targetDir string, draft
|
|||
return nil
|
||||
}
|
||||
|
||||
jww.TRACE.Println(filename, postDate, postName)
|
||||
log.Println(filename, postDate, postName)
|
||||
|
||||
targetFile := filepath.Join(targetDir, relPath)
|
||||
targetParentDir := filepath.Dir(targetFile)
|
||||
|
@ -367,7 +366,7 @@ func (c *importCommand) copyJekyllFilesAndFolders(jekyllRoot, dest string, jekyl
|
|||
if _, ok := jekyllPostDirs[entry.Name()]; !ok {
|
||||
err = hugio.CopyDir(fs, sfp, dfp, nil)
|
||||
if err != nil {
|
||||
jww.ERROR.Println(err)
|
||||
c.r.logger.Errorln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +387,7 @@ func (c *importCommand) copyJekyllFilesAndFolders(jekyllRoot, dest string, jekyl
|
|||
if !isExcept && entry.Name()[0] != '.' && entry.Name()[0] != '_' {
|
||||
err = hugio.CopyFile(fs, sfp, dfp)
|
||||
if err != nil {
|
||||
jww.ERROR.Println(err)
|
||||
c.r.logger.Errorln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
logErrorRe = regexp.MustCompile(`(?s)ERROR \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} `)
|
||||
logDuplicateTemplateExecuteRe = regexp.MustCompile(`: template: .*?:\d+:\d+: executing ".*?"`)
|
||||
logDuplicateTemplateParseRe = regexp.MustCompile(`: template: .*?:\d+:\d*`)
|
||||
)
|
||||
|
@ -106,9 +105,7 @@ func newServerCommand() *serverCommand {
|
|||
// Flags.
|
||||
var uninstall bool
|
||||
|
||||
var c *serverCommand
|
||||
|
||||
c = &serverCommand{
|
||||
c := &serverCommand{
|
||||
quit: make(chan bool),
|
||||
commands: []simplecobra.Commander{
|
||||
&simpleCommand{
|
||||
|
@ -654,8 +651,8 @@ func (c *serverCommand) getErrorWithContext() any {
|
|||
|
||||
m := make(map[string]any)
|
||||
|
||||
//xwm["Error"] = errors.New(cleanErrorLog(removeErrorPrefixFromLog(c.r.logger.Errors())))
|
||||
m["Error"] = errors.New(cleanErrorLog(removeErrorPrefixFromLog(c.r.logger.Errors())))
|
||||
m["Error"] = cleanErrorLog(c.r.logger.Errors())
|
||||
|
||||
m["Version"] = hugo.BuildVersionString()
|
||||
ferrors := herrors.UnwrapFileErrorsWithErrorContext(c.errState.buildErr())
|
||||
m["Files"] = ferrors
|
||||
|
@ -861,6 +858,9 @@ func (c *serverCommand) serve() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// We need the server to share the same logger as the Hugo build (for error counts etc.)
|
||||
c.r.logger = h.Log
|
||||
|
||||
if isMultiHost {
|
||||
for _, l := range conf.configs.ConfigLangs() {
|
||||
baseURLs = append(baseURLs, l.BaseURL().String())
|
||||
|
@ -1066,8 +1066,7 @@ func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
|
|||
}
|
||||
})
|
||||
|
||||
// prevent spamming the log on changes
|
||||
logger := helpers.NewDistinctErrorLogger()
|
||||
logger := s.c.r.logger
|
||||
|
||||
for _, ev := range staticEvents {
|
||||
// Due to our approach of layering both directories and the content's rendered output
|
||||
|
@ -1206,10 +1205,6 @@ func pickOneWriteOrCreatePath(events []fsnotify.Event) string {
|
|||
return name
|
||||
}
|
||||
|
||||
func removeErrorPrefixFromLog(content string) string {
|
||||
return logErrorRe.ReplaceAllLiteralString(content, "")
|
||||
}
|
||||
|
||||
func formatByteCount(b uint64) string {
|
||||
const unit = 1000
|
||||
if b < unit {
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright 2023 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 commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/bep/simplecobra"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func newSimpleTemplateCommand() simplecobra.Commander {
|
||||
return &simpleCommand{
|
||||
name: "template",
|
||||
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
|
||||
|
||||
return nil
|
||||
},
|
||||
withc: func(cmd *cobra.Command, r *rootCommand) {
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func newTemplateCommand() *templateCommand {
|
||||
return &templateCommand{
|
||||
commands: []simplecobra.Commander{},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type templateCommand struct {
|
||||
r *rootCommand
|
||||
|
||||
commands []simplecobra.Commander
|
||||
}
|
||||
|
||||
func (c *templateCommand) Commands() []simplecobra.Commander {
|
||||
return c.commands
|
||||
}
|
||||
|
||||
func (c *templateCommand) Name() string {
|
||||
return "template"
|
||||
}
|
||||
|
||||
func (c *templateCommand) Run(ctx context.Context, cd *simplecobra.Commandeer, args []string) error {
|
||||
conf, err := c.r.ConfigFromProvider(c.r.configVersionID.Load(), flagsToCfg(cd, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("templateCommand.Run", conf)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *templateCommand) Init(cd *simplecobra.Commandeer) error {
|
||||
cmd := cd.CobraCommand
|
||||
cmd.Short = "Print the site configuration"
|
||||
cmd.Long = `Print the site configuration, both default and custom settings.`
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *templateCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
|
||||
c.r = cd.Root.Command.(*rootCommand)
|
||||
return nil
|
||||
}
|
106
common/loggers/handlerdefault.go
Normal file
106
common/loggers/handlerdefault.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Copyright 2023 The Hugo Authors. All rights reserved.
|
||||
// Some functions in this file (see comments) is based on the Go source code,
|
||||
// copyright The Go Authors and governed by a BSD-style license.
|
||||
//
|
||||
// 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 loggers contains some basic logging setup.
|
||||
package loggers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/bep/logg"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
var bold = color.New(color.Bold)
|
||||
|
||||
// levelColor mapping.
|
||||
var levelColor = [...]*color.Color{
|
||||
logg.LevelDebug: color.New(color.FgWhite),
|
||||
logg.LevelInfo: color.New(color.FgBlue),
|
||||
logg.LevelWarn: color.New(color.FgYellow),
|
||||
logg.LevelError: color.New(color.FgRed),
|
||||
}
|
||||
|
||||
// levelString mapping.
|
||||
var levelString = [...]string{
|
||||
logg.LevelDebug: "DEBUG",
|
||||
logg.LevelInfo: "INFO ",
|
||||
logg.LevelWarn: "WARN ",
|
||||
logg.LevelError: "ERROR",
|
||||
}
|
||||
|
||||
// newDefaultHandler handler.
|
||||
func newDefaultHandler(outWriter, errWriter io.Writer) logg.Handler {
|
||||
return &defaultHandler{
|
||||
outWriter: outWriter,
|
||||
errWriter: errWriter,
|
||||
Padding: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Default Handler implementation.
|
||||
// Based on https://github.com/apex/log/blob/master/handlers/cli/cli.go
|
||||
type defaultHandler struct {
|
||||
mu sync.Mutex
|
||||
outWriter io.Writer // Defaults to os.Stdout.
|
||||
errWriter io.Writer // Defaults to os.Stderr.
|
||||
|
||||
Padding int
|
||||
}
|
||||
|
||||
// HandleLog implements logg.Handler.
|
||||
func (h *defaultHandler) HandleLog(e *logg.Entry) error {
|
||||
color := levelColor[e.Level]
|
||||
level := levelString[e.Level]
|
||||
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
var w io.Writer
|
||||
if e.Level > logg.LevelInfo {
|
||||
w = h.errWriter
|
||||
} else {
|
||||
w = h.outWriter
|
||||
}
|
||||
|
||||
var prefix string
|
||||
for _, field := range e.Fields {
|
||||
if field.Name == FieldNameCmd {
|
||||
prefix = fmt.Sprint(field.Value)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if prefix != "" {
|
||||
prefix = prefix + ": "
|
||||
}
|
||||
|
||||
color.Fprintf(w, "%s %s%s", bold.Sprintf("%*s", h.Padding+1, level), color.Sprint(prefix), e.Message)
|
||||
|
||||
for _, field := range e.Fields {
|
||||
if strings.HasPrefix(field.Name, reservedFieldNamePrefix) {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, " %s %v", color.Sprint(field.Name), field.Value)
|
||||
}
|
||||
|
||||
fmt.Fprintln(w)
|
||||
|
||||
return nil
|
||||
}
|
158
common/loggers/handlersmisc.go
Normal file
158
common/loggers/handlersmisc.go
Normal file
|
@ -0,0 +1,158 @@
|
|||
// Copyright 2023 The Hugo Authors. All rights reserved.
|
||||
// Some functions in this file (see comments) is based on the Go source code,
|
||||
// copyright The Go Authors and governed by a BSD-style license.
|
||||
//
|
||||
// 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 loggers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
)
|
||||
|
||||
// PanicOnWarningHook panics on warnings.
|
||||
var PanicOnWarningHook = func(e *logg.Entry) error {
|
||||
if e.Level != logg.LevelWarn {
|
||||
return nil
|
||||
}
|
||||
panic(e.Message)
|
||||
}
|
||||
|
||||
func newLogLevelCounter() *logLevelCounter {
|
||||
return &logLevelCounter{
|
||||
counters: make(map[logg.Level]int),
|
||||
}
|
||||
}
|
||||
|
||||
func newLogOnceHandler(threshold logg.Level) *logOnceHandler {
|
||||
return &logOnceHandler{
|
||||
threshold: threshold,
|
||||
seen: make(map[uint64]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func newStopHandler(h ...logg.Handler) *stopHandler {
|
||||
return &stopHandler{
|
||||
handlers: h,
|
||||
}
|
||||
}
|
||||
|
||||
func newSuppressStatementsHandler(statements map[string]bool) *suppressStatementsHandler {
|
||||
return &suppressStatementsHandler{
|
||||
statements: statements,
|
||||
}
|
||||
}
|
||||
|
||||
type logLevelCounter struct {
|
||||
mu sync.RWMutex
|
||||
counters map[logg.Level]int
|
||||
}
|
||||
|
||||
func (h *logLevelCounter) HandleLog(e *logg.Entry) error {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
h.counters[e.Level]++
|
||||
return nil
|
||||
}
|
||||
|
||||
var stopError = fmt.Errorf("stop")
|
||||
|
||||
type logOnceHandler struct {
|
||||
threshold logg.Level
|
||||
mu sync.Mutex
|
||||
seen map[uint64]bool
|
||||
}
|
||||
|
||||
func (h *logOnceHandler) HandleLog(e *logg.Entry) error {
|
||||
if e.Level < h.threshold {
|
||||
// We typically only want to enable this for warnings and above.
|
||||
// The common use case is that many go routines may log the same error.
|
||||
return nil
|
||||
}
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
hash := identity.HashUint64(e.Level, e.Message, e.Fields)
|
||||
if h.seen[hash] {
|
||||
return stopError
|
||||
}
|
||||
h.seen[hash] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *logOnceHandler) reset() {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
h.seen = make(map[uint64]bool)
|
||||
}
|
||||
|
||||
type stopHandler struct {
|
||||
handlers []logg.Handler
|
||||
}
|
||||
|
||||
// HandleLog implements logg.Handler.
|
||||
func (h *stopHandler) HandleLog(e *logg.Entry) error {
|
||||
for _, handler := range h.handlers {
|
||||
if err := handler.HandleLog(e); err != nil {
|
||||
if err == stopError {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type suppressStatementsHandler struct {
|
||||
statements map[string]bool
|
||||
}
|
||||
|
||||
func (h *suppressStatementsHandler) HandleLog(e *logg.Entry) error {
|
||||
for _, field := range e.Fields {
|
||||
if field.Name == FieldNameStatementID {
|
||||
if h.statements[field.Value.(string)] {
|
||||
return stopError
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// replacer creates a new log handler that does string replacement in log messages.
|
||||
func replacer(repl *strings.Replacer) logg.Handler {
|
||||
return logg.HandlerFunc(func(e *logg.Entry) error {
|
||||
e.Message = repl.Replace(e.Message)
|
||||
for i, field := range e.Fields {
|
||||
if s, ok := field.Value.(string); ok {
|
||||
e.Fields[i].Value = repl.Replace(s)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// whiteSpaceTrimmer creates a new log handler that trims whitespace from log messages and string fields.
|
||||
func whiteSpaceTrimmer() logg.Handler {
|
||||
return logg.HandlerFunc(func(e *logg.Entry) error {
|
||||
e.Message = strings.TrimSpace(e.Message)
|
||||
for i, field := range e.Fields {
|
||||
if s, ok := field.Value.(string); ok {
|
||||
e.Fields[i].Value = strings.TrimSpace(s)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
90
common/loggers/handlerterminal.go
Normal file
90
common/loggers/handlerterminal.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2023 The Hugo Authors. All rights reserved.
|
||||
// Some functions in this file (see comments) is based on the Go source code,
|
||||
// copyright The Go Authors and governed by a BSD-style license.
|
||||
//
|
||||
// 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 loggers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/bep/logg"
|
||||
)
|
||||
|
||||
// newNoColoursHandler creates a new NoColoursHandler
|
||||
func newNoColoursHandler(outWriter, errWriter io.Writer, noLevelPrefix bool, predicate func(*logg.Entry) bool) *noColoursHandler {
|
||||
if predicate == nil {
|
||||
predicate = func(e *logg.Entry) bool { return true }
|
||||
}
|
||||
return &noColoursHandler{
|
||||
noLevelPrefix: noLevelPrefix,
|
||||
outWriter: outWriter,
|
||||
errWriter: errWriter,
|
||||
predicate: predicate,
|
||||
}
|
||||
}
|
||||
|
||||
type noColoursHandler struct {
|
||||
mu sync.Mutex
|
||||
outWriter io.Writer // Defaults to os.Stdout.
|
||||
errWriter io.Writer // Defaults to os.Stderr.
|
||||
predicate func(*logg.Entry) bool
|
||||
noLevelPrefix bool
|
||||
}
|
||||
|
||||
func (h *noColoursHandler) HandleLog(e *logg.Entry) error {
|
||||
if !h.predicate(e) {
|
||||
return nil
|
||||
}
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
var w io.Writer
|
||||
if e.Level > logg.LevelInfo {
|
||||
w = h.errWriter
|
||||
} else {
|
||||
w = h.outWriter
|
||||
}
|
||||
|
||||
var prefix string
|
||||
for _, field := range e.Fields {
|
||||
if field.Name == FieldNameCmd {
|
||||
prefix = fmt.Sprint(field.Value)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if prefix != "" {
|
||||
prefix = prefix + ": "
|
||||
}
|
||||
|
||||
if h.noLevelPrefix {
|
||||
fmt.Fprintf(w, "%s%s", prefix, e.Message)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s %s%s", levelString[e.Level], prefix, e.Message)
|
||||
}
|
||||
|
||||
for _, field := range e.Fields {
|
||||
if strings.HasPrefix(field.Name, reservedFieldNamePrefix) {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, " %s %q", field.Name, field.Value)
|
||||
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright 2020 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 loggers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// IgnorableLogger is a logger that ignores certain log statements.
|
||||
type IgnorableLogger interface {
|
||||
Logger
|
||||
Errorsf(statementID, format string, v ...any)
|
||||
Apply(logger Logger) IgnorableLogger
|
||||
}
|
||||
|
||||
type ignorableLogger struct {
|
||||
Logger
|
||||
statements map[string]bool
|
||||
}
|
||||
|
||||
// NewIgnorableLogger wraps the given logger and ignores the log statement IDs given.
|
||||
func NewIgnorableLogger(logger Logger, statements map[string]bool) IgnorableLogger {
|
||||
if statements == nil {
|
||||
statements = make(map[string]bool)
|
||||
}
|
||||
return ignorableLogger{
|
||||
Logger: logger,
|
||||
statements: statements,
|
||||
}
|
||||
}
|
||||
|
||||
// Errorsf logs statementID as an ERROR if not configured as ignoreable.
|
||||
func (l ignorableLogger) Errorsf(statementID, format string, v ...any) {
|
||||
if l.statements[statementID] {
|
||||
// Ignore.
|
||||
return
|
||||
}
|
||||
ignoreMsg := fmt.Sprintf(`
|
||||
If you feel that this should not be logged as an ERROR, you can ignore it by adding this to your site config:
|
||||
ignoreErrors = [%q]`, statementID)
|
||||
|
||||
format += ignoreMsg
|
||||
|
||||
l.Errorf(format, v...)
|
||||
}
|
||||
|
||||
func (l ignorableLogger) Apply(logger Logger) IgnorableLogger {
|
||||
return ignorableLogger{
|
||||
Logger: logger,
|
||||
statements: l.statements,
|
||||
}
|
||||
}
|
303
common/loggers/logger.go
Normal file
303
common/loggers/logger.go
Normal file
|
@ -0,0 +1,303 @@
|
|||
// Copyright 2023 The Hugo Authors. All rights reserved.
|
||||
// Some functions in this file (see comments) is based on the Go source code,
|
||||
// copyright The Go Authors and governed by a BSD-style license.
|
||||
//
|
||||
// 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 loggers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/bep/logg/handlers/multi"
|
||||
"github.com/gohugoio/hugo/common/terminal"
|
||||
)
|
||||
|
||||
var (
|
||||
reservedFieldNamePrefix = "__h_field_"
|
||||
// FieldNameCmd is the name of the field that holds the command name.
|
||||
FieldNameCmd = reservedFieldNamePrefix + "_cmd"
|
||||
// Used to suppress statements.
|
||||
FieldNameStatementID = reservedFieldNamePrefix + "__h_field_statement_id"
|
||||
)
|
||||
|
||||
// Options defines options for the logger.
|
||||
type Options struct {
|
||||
Level logg.Level
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
Distinct bool
|
||||
StoreErrors bool
|
||||
HandlerPost func(e *logg.Entry) error
|
||||
SuppresssStatements map[string]bool
|
||||
}
|
||||
|
||||
// New creates a new logger with the given options.
|
||||
func New(opts Options) Logger {
|
||||
if opts.Stdout == nil {
|
||||
opts.Stdout = os.Stdout
|
||||
}
|
||||
if opts.Stderr == nil {
|
||||
opts.Stderr = os.Stdout
|
||||
}
|
||||
if opts.Level == 0 {
|
||||
opts.Level = logg.LevelWarn
|
||||
}
|
||||
|
||||
var logHandler logg.Handler
|
||||
if terminal.PrintANSIColors(os.Stdout) {
|
||||
logHandler = newDefaultHandler(opts.Stdout, opts.Stderr)
|
||||
} else {
|
||||
logHandler = newNoColoursHandler(opts.Stdout, opts.Stderr, false, nil)
|
||||
}
|
||||
|
||||
errorsw := &strings.Builder{}
|
||||
logCounters := newLogLevelCounter()
|
||||
handlers := []logg.Handler{
|
||||
whiteSpaceTrimmer(),
|
||||
logHandler,
|
||||
logCounters,
|
||||
}
|
||||
|
||||
if opts.HandlerPost != nil {
|
||||
var hookHandler logg.HandlerFunc = func(e *logg.Entry) error {
|
||||
opts.HandlerPost(e)
|
||||
return nil
|
||||
}
|
||||
handlers = append(handlers, hookHandler)
|
||||
}
|
||||
|
||||
if opts.StoreErrors {
|
||||
h := newNoColoursHandler(io.Discard, errorsw, true, func(e *logg.Entry) bool {
|
||||
return e.Level >= logg.LevelError
|
||||
})
|
||||
|
||||
handlers = append(handlers, h)
|
||||
}
|
||||
|
||||
logHandler = multi.New(handlers...)
|
||||
|
||||
var logOnce *logOnceHandler
|
||||
if opts.Distinct {
|
||||
logOnce = newLogOnceHandler(logg.LevelWarn)
|
||||
logHandler = newStopHandler(logOnce, logHandler)
|
||||
}
|
||||
|
||||
if opts.SuppresssStatements != nil && len(opts.SuppresssStatements) > 0 {
|
||||
logHandler = newStopHandler(newSuppressStatementsHandler(opts.SuppresssStatements), logHandler)
|
||||
}
|
||||
|
||||
logger := logg.New(
|
||||
logg.Options{
|
||||
Level: opts.Level,
|
||||
Handler: logHandler,
|
||||
},
|
||||
)
|
||||
|
||||
l := logger.WithLevel(opts.Level)
|
||||
|
||||
reset := func() {
|
||||
logCounters.mu.Lock()
|
||||
defer logCounters.mu.Unlock()
|
||||
logCounters.counters = make(map[logg.Level]int)
|
||||
errorsw.Reset()
|
||||
if logOnce != nil {
|
||||
logOnce.reset()
|
||||
}
|
||||
}
|
||||
|
||||
return &logAdapter{
|
||||
logCounters: logCounters,
|
||||
errors: errorsw,
|
||||
reset: reset,
|
||||
out: opts.Stdout,
|
||||
level: opts.Level,
|
||||
logger: logger,
|
||||
debugl: l.WithLevel(logg.LevelDebug),
|
||||
infol: l.WithLevel(logg.LevelInfo),
|
||||
warnl: l.WithLevel(logg.LevelWarn),
|
||||
errorl: l.WithLevel(logg.LevelError),
|
||||
}
|
||||
}
|
||||
|
||||
// NewDefault creates a new logger with the default options.
|
||||
func NewDefault() Logger {
|
||||
opts := Options{
|
||||
Distinct: true,
|
||||
Level: logg.LevelWarn,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stdout,
|
||||
}
|
||||
return New(opts)
|
||||
}
|
||||
|
||||
func LevelLoggerToWriter(l logg.LevelLogger) io.Writer {
|
||||
return logWriter{l: l}
|
||||
}
|
||||
|
||||
type Logger interface {
|
||||
Debugf(format string, v ...any)
|
||||
Debugln(v ...any)
|
||||
Error() logg.LevelLogger
|
||||
Errorf(format string, v ...any)
|
||||
Errorln(v ...any)
|
||||
Errors() string
|
||||
Errorsf(id, format string, v ...any)
|
||||
Info() logg.LevelLogger
|
||||
InfoCommand(command string) logg.LevelLogger
|
||||
Infof(format string, v ...any)
|
||||
Infoln(v ...any)
|
||||
Level() logg.Level
|
||||
LoggCount(logg.Level) int
|
||||
Logger() logg.Logger
|
||||
Out() io.Writer
|
||||
Printf(format string, v ...any)
|
||||
Println(v ...any)
|
||||
PrintTimerIfDelayed(start time.Time, name string)
|
||||
Reset()
|
||||
Warn() logg.LevelLogger
|
||||
WarnCommand(command string) logg.LevelLogger
|
||||
Warnf(format string, v ...any)
|
||||
Warnln(v ...any)
|
||||
}
|
||||
|
||||
type logAdapter struct {
|
||||
logCounters *logLevelCounter
|
||||
errors *strings.Builder
|
||||
reset func()
|
||||
out io.Writer
|
||||
level logg.Level
|
||||
logger logg.Logger
|
||||
debugl logg.LevelLogger
|
||||
infol logg.LevelLogger
|
||||
warnl logg.LevelLogger
|
||||
errorl logg.LevelLogger
|
||||
}
|
||||
|
||||
func (l *logAdapter) Debugf(format string, v ...any) {
|
||||
l.debugl.Logf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Debugln(v ...any) {
|
||||
l.debugl.Logf(l.sprint(v...))
|
||||
}
|
||||
|
||||
func (l *logAdapter) Info() logg.LevelLogger {
|
||||
return l.infol
|
||||
}
|
||||
|
||||
func (l *logAdapter) InfoCommand(command string) logg.LevelLogger {
|
||||
return l.infol.WithField(FieldNameCmd, command)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Infof(format string, v ...any) {
|
||||
l.infol.Logf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Infoln(v ...any) {
|
||||
l.infol.Logf(l.sprint(v...))
|
||||
}
|
||||
|
||||
func (l *logAdapter) Level() logg.Level {
|
||||
return l.level
|
||||
}
|
||||
|
||||
func (l *logAdapter) LoggCount(level logg.Level) int {
|
||||
l.logCounters.mu.RLock()
|
||||
defer l.logCounters.mu.RUnlock()
|
||||
return l.logCounters.counters[level]
|
||||
}
|
||||
|
||||
func (l *logAdapter) Logger() logg.Logger {
|
||||
return l.logger
|
||||
}
|
||||
|
||||
func (l *logAdapter) Out() io.Writer {
|
||||
return l.out
|
||||
}
|
||||
|
||||
// PrintTimerIfDelayed prints a time statement to the FEEDBACK logger
|
||||
// if considerable time is spent.
|
||||
func (l *logAdapter) PrintTimerIfDelayed(start time.Time, name string) {
|
||||
elapsed := time.Since(start)
|
||||
milli := int(1000 * elapsed.Seconds())
|
||||
if milli < 500 {
|
||||
return
|
||||
}
|
||||
l.Printf("%s in %v ms", name, milli)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Printf(format string, v ...any) {
|
||||
fmt.Fprintf(l.out, format, v...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Println(v ...any) {
|
||||
fmt.Fprintln(l.out, v...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Reset() {
|
||||
l.reset()
|
||||
}
|
||||
|
||||
func (l *logAdapter) Warn() logg.LevelLogger {
|
||||
return l.warnl
|
||||
}
|
||||
|
||||
func (l *logAdapter) Warnf(format string, v ...any) {
|
||||
l.warnl.Logf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) WarnCommand(command string) logg.LevelLogger {
|
||||
return l.warnl.WithField(FieldNameCmd, command)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Warnln(v ...any) {
|
||||
l.warnl.Logf(l.sprint(v...))
|
||||
}
|
||||
|
||||
func (l *logAdapter) Error() logg.LevelLogger {
|
||||
return l.errorl
|
||||
}
|
||||
|
||||
func (l *logAdapter) Errorf(format string, v ...any) {
|
||||
l.errorl.Logf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Errorln(v ...any) {
|
||||
l.errorl.Logf(l.sprint(v...))
|
||||
}
|
||||
|
||||
func (l *logAdapter) Errors() string {
|
||||
return l.errors.String()
|
||||
}
|
||||
|
||||
func (l *logAdapter) Errorsf(id, format string, v ...any) {
|
||||
l.errorl.WithField(FieldNameStatementID, id).Logf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logAdapter) sprint(v ...any) string {
|
||||
return strings.TrimRight(fmt.Sprintln(v...), "\n")
|
||||
}
|
||||
|
||||
type logWriter struct {
|
||||
l logg.LevelLogger
|
||||
}
|
||||
|
||||
func (w logWriter) Write(p []byte) (n int, err error) {
|
||||
w.l.Logf("%s", p)
|
||||
return len(p), nil
|
||||
}
|
156
common/loggers/logger_test.go
Normal file
156
common/loggers/logger_test.go
Normal file
|
@ -0,0 +1,156 @@
|
|||
// Copyright 2023 The Hugo Authors. All rights reserved.
|
||||
// Some functions in this file (see comments) is based on the Go source code,
|
||||
// copyright The Go Authors and governed by a BSD-style license.
|
||||
//
|
||||
// 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 loggers_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
)
|
||||
|
||||
func TestLogDistinct(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
opts := loggers.Options{
|
||||
Distinct: true,
|
||||
StoreErrors: true,
|
||||
Stdout: io.Discard,
|
||||
Stderr: io.Discard,
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
l.Errorln("error 1")
|
||||
l.Errorln("error 2")
|
||||
l.Warnln("warn 1")
|
||||
}
|
||||
c.Assert(strings.Count(l.Errors(), "error 1"), qt.Equals, 1)
|
||||
c.Assert(l.LoggCount(logg.LevelError), qt.Equals, 2)
|
||||
c.Assert(l.LoggCount(logg.LevelWarn), qt.Equals, 1)
|
||||
}
|
||||
|
||||
func TestHookLast(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
opts := loggers.Options{
|
||||
HandlerPost: func(e *logg.Entry) error {
|
||||
panic(e.Message)
|
||||
},
|
||||
Stdout: io.Discard,
|
||||
Stderr: io.Discard,
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
|
||||
c.Assert(func() { l.Warnln("warn 1") }, qt.PanicMatches, "warn 1")
|
||||
}
|
||||
|
||||
func TestOptionStoreErrors(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
var sb strings.Builder
|
||||
|
||||
opts := loggers.Options{
|
||||
StoreErrors: true,
|
||||
Stderr: &sb,
|
||||
Stdout: &sb,
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
l.Errorln("error 1")
|
||||
l.Errorln("error 2")
|
||||
|
||||
errorsStr := l.Errors()
|
||||
|
||||
c.Assert(errorsStr, qt.Contains, "error 1")
|
||||
c.Assert(errorsStr, qt.Not(qt.Contains), "ERROR")
|
||||
|
||||
c.Assert(sb.String(), qt.Contains, "error 1")
|
||||
c.Assert(sb.String(), qt.Contains, "ERROR")
|
||||
|
||||
}
|
||||
|
||||
func TestLogCount(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
opts := loggers.Options{
|
||||
StoreErrors: true,
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
l.Errorln("error 1")
|
||||
l.Errorln("error 2")
|
||||
l.Warnln("warn 1")
|
||||
|
||||
c.Assert(l.LoggCount(logg.LevelError), qt.Equals, 2)
|
||||
c.Assert(l.LoggCount(logg.LevelWarn), qt.Equals, 1)
|
||||
c.Assert(l.LoggCount(logg.LevelInfo), qt.Equals, 0)
|
||||
}
|
||||
|
||||
func TestSuppressStatements(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
opts := loggers.Options{
|
||||
StoreErrors: true,
|
||||
SuppresssStatements: map[string]bool{
|
||||
"error-1": true,
|
||||
},
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
l.Error().WithField(loggers.FieldNameStatementID, "error-1").Logf("error 1")
|
||||
l.Errorln("error 2")
|
||||
|
||||
errorsStr := l.Errors()
|
||||
|
||||
c.Assert(errorsStr, qt.Not(qt.Contains), "error 1")
|
||||
c.Assert(errorsStr, qt.Contains, "error 2")
|
||||
c.Assert(l.LoggCount(logg.LevelError), qt.Equals, 1)
|
||||
|
||||
}
|
||||
|
||||
func TestReset(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
opts := loggers.Options{
|
||||
StoreErrors: true,
|
||||
Distinct: true,
|
||||
Stdout: io.Discard,
|
||||
Stderr: io.Discard,
|
||||
}
|
||||
|
||||
l := loggers.New(opts)
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
l.Errorln("error 1")
|
||||
l.Errorln("error 2")
|
||||
l.Errorln("error 1")
|
||||
c.Assert(l.LoggCount(logg.LevelError), qt.Equals, 2)
|
||||
|
||||
l.Reset()
|
||||
|
||||
errorsStr := l.Errors()
|
||||
|
||||
c.Assert(errorsStr, qt.Equals, "")
|
||||
c.Assert(l.LoggCount(logg.LevelError), qt.Equals, 0)
|
||||
|
||||
}
|
||||
}
|
53
common/loggers/loggerglobal.go
Normal file
53
common/loggers/loggerglobal.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2023 The Hugo Authors. All rights reserved.
|
||||
// Some functions in this file (see comments) is based on the Go source code,
|
||||
// copyright The Go Authors and governed by a BSD-style license.
|
||||
//
|
||||
// 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 loggers
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/bep/logg"
|
||||
)
|
||||
|
||||
func InitGlobalLogger(panicOnWarnings bool) {
|
||||
logMu.Lock()
|
||||
defer logMu.Unlock()
|
||||
var logHookLast func(e *logg.Entry) error
|
||||
if panicOnWarnings {
|
||||
logHookLast = PanicOnWarningHook
|
||||
}
|
||||
|
||||
log = New(
|
||||
Options{
|
||||
Distinct: true,
|
||||
HandlerPost: logHookLast,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
var logMu sync.Mutex
|
||||
|
||||
func Log() Logger {
|
||||
logMu.Lock()
|
||||
defer logMu.Unlock()
|
||||
return log
|
||||
}
|
||||
|
||||
// The global logger.
|
||||
var log Logger
|
||||
|
||||
func init() {
|
||||
InitGlobalLogger(false)
|
||||
}
|
|
@ -1,355 +0,0 @@
|
|||
// Copyright 2020 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 loggers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/common/terminal"
|
||||
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
var (
|
||||
// Counts ERROR logs to the global jww logger.
|
||||
GlobalErrorCounter *jww.Counter
|
||||
PanicOnWarning atomic.Bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
GlobalErrorCounter = &jww.Counter{}
|
||||
jww.SetLogListeners(jww.LogCounter(GlobalErrorCounter, jww.LevelError))
|
||||
}
|
||||
|
||||
func LoggerToWriterWithPrefix(logger *log.Logger, prefix string) io.Writer {
|
||||
return prefixWriter{
|
||||
logger: logger,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
type prefixWriter struct {
|
||||
logger *log.Logger
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (w prefixWriter) Write(p []byte) (n int, err error) {
|
||||
w.logger.Printf("%s: %s", w.prefix, p)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
type Logger interface {
|
||||
Printf(format string, v ...any)
|
||||
Println(v ...any)
|
||||
PrintTimerIfDelayed(start time.Time, name string)
|
||||
Debug() *log.Logger
|
||||
Debugf(format string, v ...any)
|
||||
Debugln(v ...any)
|
||||
Info() *log.Logger
|
||||
Infof(format string, v ...any)
|
||||
Infoln(v ...any)
|
||||
Warn() *log.Logger
|
||||
Warnf(format string, v ...any)
|
||||
Warnln(v ...any)
|
||||
Error() *log.Logger
|
||||
Errorf(format string, v ...any)
|
||||
Errorln(v ...any)
|
||||
Errors() string
|
||||
|
||||
Out() io.Writer
|
||||
|
||||
Reset()
|
||||
|
||||
// Used in tests.
|
||||
LogCounters() *LogCounters
|
||||
}
|
||||
|
||||
type LogCounters struct {
|
||||
ErrorCounter *jww.Counter
|
||||
WarnCounter *jww.Counter
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
*jww.Notepad
|
||||
|
||||
// The writer that represents stdout.
|
||||
// Will be io.Discard when in quiet mode.
|
||||
out io.Writer
|
||||
|
||||
logCounters *LogCounters
|
||||
|
||||
// This is only set in server mode.
|
||||
errors *bytes.Buffer
|
||||
}
|
||||
|
||||
func (l *logger) Printf(format string, v ...any) {
|
||||
l.FEEDBACK.Printf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logger) Println(v ...any) {
|
||||
l.FEEDBACK.Println(v...)
|
||||
}
|
||||
|
||||
func (l *logger) Debug() *log.Logger {
|
||||
return l.DEBUG
|
||||
}
|
||||
|
||||
func (l *logger) Debugf(format string, v ...any) {
|
||||
l.DEBUG.Printf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logger) Debugln(v ...any) {
|
||||
l.DEBUG.Println(v...)
|
||||
}
|
||||
|
||||
func (l *logger) Infof(format string, v ...any) {
|
||||
l.INFO.Printf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logger) Infoln(v ...any) {
|
||||
l.INFO.Println(v...)
|
||||
}
|
||||
|
||||
func (l *logger) Info() *log.Logger {
|
||||
return l.INFO
|
||||
}
|
||||
|
||||
const panicOnWarningMessage = "Warning trapped. Remove the --panicOnWarning flag to continue."
|
||||
|
||||
func (l *logger) Warnf(format string, v ...any) {
|
||||
l.WARN.Printf(format, v...)
|
||||
if PanicOnWarning.Load() {
|
||||
panic(panicOnWarningMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) Warnln(v ...any) {
|
||||
l.WARN.Println(v...)
|
||||
if PanicOnWarning.Load() {
|
||||
panic(panicOnWarningMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) Warn() *log.Logger {
|
||||
return l.WARN
|
||||
}
|
||||
|
||||
func (l *logger) Errorf(format string, v ...any) {
|
||||
l.ERROR.Printf(format, v...)
|
||||
}
|
||||
|
||||
func (l *logger) Errorln(v ...any) {
|
||||
l.ERROR.Println(v...)
|
||||
}
|
||||
|
||||
func (l *logger) Error() *log.Logger {
|
||||
return l.ERROR
|
||||
}
|
||||
|
||||
func (l *logger) LogCounters() *LogCounters {
|
||||
return l.logCounters
|
||||
}
|
||||
|
||||
func (l *logger) Out() io.Writer {
|
||||
return l.out
|
||||
}
|
||||
|
||||
// PrintTimerIfDelayed prints a time statement to the FEEDBACK logger
|
||||
// if considerable time is spent.
|
||||
func (l *logger) PrintTimerIfDelayed(start time.Time, name string) {
|
||||
elapsed := time.Since(start)
|
||||
milli := int(1000 * elapsed.Seconds())
|
||||
if milli < 500 {
|
||||
return
|
||||
}
|
||||
l.Printf("%s in %v ms", name, milli)
|
||||
}
|
||||
|
||||
func (l *logger) PrintTimer(start time.Time, name string) {
|
||||
elapsed := time.Since(start)
|
||||
milli := int(1000 * elapsed.Seconds())
|
||||
l.Printf("%s in %v ms", name, milli)
|
||||
}
|
||||
|
||||
func (l *logger) Errors() string {
|
||||
if l.errors == nil {
|
||||
return ""
|
||||
}
|
||||
return ansiColorRe.ReplaceAllString(l.errors.String(), "")
|
||||
}
|
||||
|
||||
// Reset resets the logger's internal state.
|
||||
func (l *logger) Reset() {
|
||||
l.logCounters.ErrorCounter.Reset()
|
||||
if l.errors != nil {
|
||||
l.errors.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
// NewLogger creates a new Logger for the given thresholds
|
||||
func NewLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) Logger {
|
||||
return newLogger(stdoutThreshold, logThreshold, outHandle, logHandle, saveErrors)
|
||||
}
|
||||
|
||||
// NewDebugLogger is a convenience function to create a debug logger.
|
||||
func NewDebugLogger() Logger {
|
||||
return NewBasicLogger(jww.LevelDebug)
|
||||
}
|
||||
|
||||
// NewWarningLogger is a convenience function to create a warning logger.
|
||||
func NewWarningLogger() Logger {
|
||||
return NewBasicLogger(jww.LevelWarn)
|
||||
}
|
||||
|
||||
// NewInfoLogger is a convenience function to create a info logger.
|
||||
func NewInfoLogger() Logger {
|
||||
return NewBasicLogger(jww.LevelInfo)
|
||||
}
|
||||
|
||||
// NewErrorLogger is a convenience function to create an error logger.
|
||||
func NewErrorLogger() Logger {
|
||||
return NewBasicLogger(jww.LevelError)
|
||||
}
|
||||
|
||||
// NewBasicLogger creates a new basic logger writing to Stdout.
|
||||
func NewBasicLogger(t jww.Threshold) Logger {
|
||||
return newLogger(t, jww.LevelError, os.Stdout, io.Discard, false)
|
||||
}
|
||||
|
||||
// NewBasicLoggerForWriter creates a new basic logger writing to w.
|
||||
func NewBasicLoggerForWriter(t jww.Threshold, w io.Writer) Logger {
|
||||
return newLogger(t, jww.LevelError, w, io.Discard, false)
|
||||
}
|
||||
|
||||
// RemoveANSIColours removes all ANSI colours from the given string.
|
||||
func RemoveANSIColours(s string) string {
|
||||
return ansiColorRe.ReplaceAllString(s, "")
|
||||
}
|
||||
|
||||
var (
|
||||
ansiColorRe = regexp.MustCompile("(?s)\\033\\[\\d*(;\\d*)*m")
|
||||
errorRe = regexp.MustCompile("^(ERROR|FATAL|WARN)")
|
||||
)
|
||||
|
||||
type ansiCleaner struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (a ansiCleaner) Write(p []byte) (n int, err error) {
|
||||
return a.w.Write(ansiColorRe.ReplaceAll(p, []byte("")))
|
||||
}
|
||||
|
||||
type labelColorizer struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (a labelColorizer) Write(p []byte) (n int, err error) {
|
||||
replaced := errorRe.ReplaceAllStringFunc(string(p), func(m string) string {
|
||||
switch m {
|
||||
case "ERROR", "FATAL":
|
||||
return terminal.Error(m)
|
||||
case "WARN":
|
||||
return terminal.Warning(m)
|
||||
default:
|
||||
return m
|
||||
}
|
||||
})
|
||||
// io.MultiWriter will abort if we return a bigger write count than input
|
||||
// bytes, so we lie a little.
|
||||
_, err = a.w.Write([]byte(replaced))
|
||||
return len(p), err
|
||||
}
|
||||
|
||||
// InitGlobalLogger initializes the global logger, used in some rare cases.
|
||||
func InitGlobalLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer) {
|
||||
outHandle, logHandle = getLogWriters(outHandle, logHandle)
|
||||
|
||||
jww.SetStdoutOutput(outHandle)
|
||||
jww.SetLogOutput(logHandle)
|
||||
jww.SetLogThreshold(logThreshold)
|
||||
jww.SetStdoutThreshold(stdoutThreshold)
|
||||
}
|
||||
|
||||
func getLogWriters(outHandle, logHandle io.Writer) (io.Writer, io.Writer) {
|
||||
isTerm := terminal.PrintANSIColors(os.Stdout)
|
||||
if logHandle != io.Discard && isTerm {
|
||||
// Remove any Ansi coloring from log output
|
||||
logHandle = ansiCleaner{w: logHandle}
|
||||
}
|
||||
|
||||
if isTerm {
|
||||
outHandle = labelColorizer{w: outHandle}
|
||||
}
|
||||
|
||||
return outHandle, logHandle
|
||||
}
|
||||
|
||||
type fatalLogWriter int
|
||||
|
||||
func (s fatalLogWriter) Write(p []byte) (n int, err error) {
|
||||
trace := make([]byte, 1500)
|
||||
runtime.Stack(trace, true)
|
||||
fmt.Printf("\n===========\n\n%s\n", trace)
|
||||
os.Exit(-1)
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var fatalLogListener = func(t jww.Threshold) io.Writer {
|
||||
if t != jww.LevelError {
|
||||
// Only interested in ERROR
|
||||
return nil
|
||||
}
|
||||
|
||||
return new(fatalLogWriter)
|
||||
}
|
||||
|
||||
func newLogger(stdoutThreshold, logThreshold jww.Threshold, outHandle, logHandle io.Writer, saveErrors bool) *logger {
|
||||
errorCounter := &jww.Counter{}
|
||||
warnCounter := &jww.Counter{}
|
||||
outHandle, logHandle = getLogWriters(outHandle, logHandle)
|
||||
|
||||
listeners := []jww.LogListener{jww.LogCounter(errorCounter, jww.LevelError), jww.LogCounter(warnCounter, jww.LevelWarn)}
|
||||
var errorBuff *bytes.Buffer
|
||||
if saveErrors {
|
||||
errorBuff = new(bytes.Buffer)
|
||||
errorCapture := func(t jww.Threshold) io.Writer {
|
||||
if t != jww.LevelError {
|
||||
// Only interested in ERROR
|
||||
return nil
|
||||
}
|
||||
return errorBuff
|
||||
}
|
||||
|
||||
listeners = append(listeners, errorCapture)
|
||||
}
|
||||
|
||||
return &logger{
|
||||
Notepad: jww.NewNotepad(stdoutThreshold, logThreshold, outHandle, logHandle, "", log.Ldate|log.Ltime, listeners...),
|
||||
out: outHandle,
|
||||
logCounters: &LogCounters{
|
||||
ErrorCounter: errorCounter,
|
||||
WarnCounter: warnCounter,
|
||||
},
|
||||
errors: errorBuff,
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
// 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 loggers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestLogger(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
l := NewWarningLogger()
|
||||
|
||||
l.Errorln("One error")
|
||||
l.Errorln("Two error")
|
||||
l.Warnln("A warning")
|
||||
|
||||
c.Assert(l.LogCounters().ErrorCounter.Count(), qt.Equals, uint64(2))
|
||||
}
|
||||
|
||||
func TestLoggerToWriterWithPrefix(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
logger := log.New(&b, "", 0)
|
||||
|
||||
w := LoggerToWriterWithPrefix(logger, "myprefix")
|
||||
|
||||
fmt.Fprint(w, "Hello Hugo!")
|
||||
|
||||
c.Assert(b.String(), qt.Equals, "myprefix: Hello Hugo!\n")
|
||||
}
|
||||
|
||||
func TestRemoveANSIColours(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
c.Assert(RemoveANSIColours(""), qt.Equals, "")
|
||||
c.Assert(RemoveANSIColours("\033[31m"), qt.Equals, "")
|
||||
c.Assert(RemoveANSIColours("\033[31mHello"), qt.Equals, "Hello")
|
||||
c.Assert(RemoveANSIColours("\033[31mHello\033[0m"), qt.Equals, "Hello")
|
||||
c.Assert(RemoveANSIColours("\033[31mHello\033[0m World"), qt.Equals, "Hello World")
|
||||
c.Assert(RemoveANSIColours("\033[31mHello\033[0m World\033[31m!"), qt.Equals, "Hello World!")
|
||||
c.Assert(RemoveANSIColours("\x1b[90m 5 |"), qt.Equals, " 5 |")
|
||||
}
|
|
@ -490,6 +490,9 @@ type RootConfig struct {
|
|||
// ENable to print warnings for multiple files published to the same destination.
|
||||
LogPathWarnings bool
|
||||
|
||||
// Enable to panic on warning log entries. This may make it easier to detect the source.
|
||||
PanicOnWarning bool
|
||||
|
||||
// The configured environment. Default is "development" for server and "production" for build.
|
||||
Environment string
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ func LoadConfig(d ConfigSourceDescriptor) (*Configs, error) {
|
|||
}
|
||||
|
||||
if d.Logger == nil {
|
||||
d.Logger = loggers.NewErrorLogger()
|
||||
d.Logger = loggers.NewDefault()
|
||||
}
|
||||
|
||||
l := &configLoader{ConfigSourceDescriptor: d, cfg: config.New()}
|
||||
|
@ -90,8 +90,9 @@ func LoadConfig(d ConfigSourceDescriptor) (*Configs, error) {
|
|||
return nil, fmt.Errorf("failed to init config: %w", err)
|
||||
}
|
||||
|
||||
// This is unfortunate, but this is a global setting.
|
||||
// This is unfortunate, but these are global settings.
|
||||
tpl.SetSecurityAllowActionJSTmpl(configs.Base.Security.GoTemplates.AllowActionJSTmpl)
|
||||
loggers.InitGlobalLogger(configs.Base.PanicOnWarning)
|
||||
|
||||
return configs, nil
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/types"
|
||||
|
@ -306,6 +307,7 @@ func (c *CacheBuster) CompileConfig(logger loggers.Logger) error {
|
|||
if c.compiledSource != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
source := c.Source
|
||||
target := c.Target
|
||||
sourceRe, err := regexp.Compile(source)
|
||||
|
@ -313,6 +315,8 @@ func (c *CacheBuster) CompileConfig(logger loggers.Logger) error {
|
|||
return fmt.Errorf("failed to compile cache buster source %q: %w", c.Source, err)
|
||||
}
|
||||
var compileErr error
|
||||
debugl := logger.Logger().WithLevel(logg.LevelDebug).WithField(loggers.FieldNameCmd, "cachebuster")
|
||||
|
||||
c.compiledSource = func(s string) func(string) bool {
|
||||
m := sourceRe.FindStringSubmatch(s)
|
||||
matchString := "no match"
|
||||
|
@ -320,7 +324,7 @@ func (c *CacheBuster) CompileConfig(logger loggers.Logger) error {
|
|||
if match {
|
||||
matchString = "match!"
|
||||
}
|
||||
logger.Debugf("cachebuster: Matching %q with source %q: %s\n", s, source, matchString)
|
||||
debugl.Logf("Matching %q with source %q: %s", s, source, matchString)
|
||||
if !match {
|
||||
return nil
|
||||
}
|
||||
|
@ -341,7 +345,7 @@ func (c *CacheBuster) CompileConfig(logger loggers.Logger) error {
|
|||
if match {
|
||||
matchString = "match!"
|
||||
}
|
||||
logger.Debugf("cachebuster: Matching %q with target %q: %s\n", s, target, matchString)
|
||||
logger.Debugf("Matching %q with target %q: %s", s, target, matchString)
|
||||
|
||||
return match
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ status = 301
|
|||
|
||||
s, err := DecodeServer(cfg)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(s.CompileConfig(loggers.NewErrorLogger()), qt.IsNil)
|
||||
c.Assert(s.CompileConfig(loggers.NewDefault()), qt.IsNil)
|
||||
|
||||
c.Assert(s.MatchHeaders("/foo.jpg"), qt.DeepEquals, []types.KeyValueStr{
|
||||
{Key: "X-Content-Type-Options", Value: "nosniff"},
|
||||
|
@ -145,7 +145,7 @@ func TestBuildConfigCacheBusters(t *testing.T) {
|
|||
c := qt.New(t)
|
||||
cfg := New()
|
||||
conf := DecodeBuildConfig(cfg)
|
||||
l := loggers.NewInfoLogger()
|
||||
l := loggers.NewDefault()
|
||||
c.Assert(conf.CompileConfig(l), qt.IsNil)
|
||||
|
||||
m, err := conf.MatchCacheBuster(l, "assets/foo/main.js")
|
||||
|
|
|
@ -37,10 +37,10 @@ import (
|
|||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
"github.com/spf13/afero"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
|
||||
"gocloud.dev/blob"
|
||||
|
@ -56,9 +56,10 @@ type Deployer struct {
|
|||
bucket *blob.Bucket
|
||||
|
||||
mediaTypes media.Types // Hugo's MediaType to guess ContentType
|
||||
quiet bool // true reduces STDOUT
|
||||
quiet bool // true reduces STDOUT // TODO(bep) remove, this is a global feature.
|
||||
|
||||
cfg DeployConfig
|
||||
cfg DeployConfig
|
||||
logger loggers.Logger
|
||||
|
||||
target *Target // the target to deploy to
|
||||
|
||||
|
@ -73,7 +74,7 @@ type deploySummary struct {
|
|||
const metaMD5Hash = "md5chksum" // the meta key to store md5hash in
|
||||
|
||||
// New constructs a new *Deployer.
|
||||
func New(cfg config.AllProvider, localFs afero.Fs) (*Deployer, error) {
|
||||
func New(cfg config.AllProvider, logger loggers.Logger, localFs afero.Fs) (*Deployer, error) {
|
||||
|
||||
dcfg := cfg.GetConfigSection(deploymentConfigKey).(DeployConfig)
|
||||
targetName := dcfg.Target
|
||||
|
@ -112,12 +113,16 @@ func (d *Deployer) openBucket(ctx context.Context) (*blob.Bucket, error) {
|
|||
if d.bucket != nil {
|
||||
return d.bucket, nil
|
||||
}
|
||||
jww.FEEDBACK.Printf("Deploying to target %q (%s)\n", d.target.Name, d.target.URL)
|
||||
d.logger.Printf("Deploying to target %q (%s)\n", d.target.Name, d.target.URL)
|
||||
return blob.OpenBucket(ctx, d.target.URL)
|
||||
}
|
||||
|
||||
// Deploy deploys the site to a target.
|
||||
func (d *Deployer) Deploy(ctx context.Context) error {
|
||||
if d.logger == nil {
|
||||
d.logger = loggers.NewDefault()
|
||||
}
|
||||
|
||||
bucket, err := d.openBucket(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -132,33 +137,33 @@ func (d *Deployer) Deploy(ctx context.Context) error {
|
|||
if d.target != nil {
|
||||
include, exclude = d.target.includeGlob, d.target.excludeGlob
|
||||
}
|
||||
local, err := walkLocal(d.localFs, d.cfg.Matchers, include, exclude, d.mediaTypes)
|
||||
local, err := d.walkLocal(d.localFs, d.cfg.Matchers, include, exclude, d.mediaTypes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jww.INFO.Printf("Found %d local files.\n", len(local))
|
||||
d.logger.Infof("Found %d local files.\n", len(local))
|
||||
d.summary.NumLocal = len(local)
|
||||
|
||||
// Load remote files from the target.
|
||||
remote, err := walkRemote(ctx, bucket, include, exclude)
|
||||
remote, err := d.walkRemote(ctx, bucket, include, exclude)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jww.INFO.Printf("Found %d remote files.\n", len(remote))
|
||||
d.logger.Infof("Found %d remote files.\n", len(remote))
|
||||
d.summary.NumRemote = len(remote)
|
||||
|
||||
// Diff local vs remote to see what changes need to be applied.
|
||||
uploads, deletes := findDiffs(local, remote, d.cfg.Force)
|
||||
uploads, deletes := d.findDiffs(local, remote, d.cfg.Force)
|
||||
d.summary.NumUploads = len(uploads)
|
||||
d.summary.NumDeletes = len(deletes)
|
||||
if len(uploads)+len(deletes) == 0 {
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Println("No changes required.")
|
||||
d.logger.Println("No changes required.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Println(summarizeChanges(uploads, deletes))
|
||||
d.logger.Println(summarizeChanges(uploads, deletes))
|
||||
}
|
||||
|
||||
// Ask for confirmation before proceeding.
|
||||
|
@ -192,14 +197,14 @@ func (d *Deployer) Deploy(ctx context.Context) error {
|
|||
for _, upload := range uploads {
|
||||
if d.cfg.DryRun {
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Printf("[DRY RUN] Would upload: %v\n", upload)
|
||||
d.logger.Printf("[DRY RUN] Would upload: %v\n", upload)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
sem <- struct{}{}
|
||||
go func(upload *fileToUpload) {
|
||||
if err := doSingleUpload(ctx, bucket, upload); err != nil {
|
||||
if err := d.doSingleUpload(ctx, bucket, upload); err != nil {
|
||||
errMu.Lock()
|
||||
defer errMu.Unlock()
|
||||
errs = append(errs, err)
|
||||
|
@ -214,7 +219,7 @@ func (d *Deployer) Deploy(ctx context.Context) error {
|
|||
}
|
||||
|
||||
if d.cfg.MaxDeletes != -1 && len(deletes) > d.cfg.MaxDeletes {
|
||||
jww.WARN.Printf("Skipping %d deletes because it is more than --maxDeletes (%d). If this is expected, set --maxDeletes to a larger number, or -1 to disable this check.\n", len(deletes), d.cfg.MaxDeletes)
|
||||
d.logger.Warnf("Skipping %d deletes because it is more than --maxDeletes (%d). If this is expected, set --maxDeletes to a larger number, or -1 to disable this check.\n", len(deletes), d.cfg.MaxDeletes)
|
||||
d.summary.NumDeletes = 0
|
||||
} else {
|
||||
// Apply deletes in parallel.
|
||||
|
@ -223,16 +228,16 @@ func (d *Deployer) Deploy(ctx context.Context) error {
|
|||
for _, del := range deletes {
|
||||
if d.cfg.DryRun {
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Printf("[DRY RUN] Would delete %s\n", del)
|
||||
d.logger.Printf("[DRY RUN] Would delete %s\n", del)
|
||||
}
|
||||
continue
|
||||
}
|
||||
sem <- struct{}{}
|
||||
go func(del string) {
|
||||
jww.INFO.Printf("Deleting %s...\n", del)
|
||||
d.logger.Infof("Deleting %s...\n", del)
|
||||
if err := bucket.Delete(ctx, del); err != nil {
|
||||
if gcerrors.Code(err) == gcerrors.NotFound {
|
||||
jww.WARN.Printf("Failed to delete %q because it wasn't found: %v", del, err)
|
||||
d.logger.Warnf("Failed to delete %q because it wasn't found: %v", del, err)
|
||||
} else {
|
||||
errMu.Lock()
|
||||
defer errMu.Unlock()
|
||||
|
@ -250,24 +255,24 @@ func (d *Deployer) Deploy(ctx context.Context) error {
|
|||
|
||||
if len(errs) > 0 {
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Printf("Encountered %d errors.\n", len(errs))
|
||||
d.logger.Printf("Encountered %d errors.\n", len(errs))
|
||||
}
|
||||
return errs[0]
|
||||
}
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Println("Success!")
|
||||
d.logger.Println("Success!")
|
||||
}
|
||||
|
||||
if d.cfg.InvalidateCDN {
|
||||
if d.target.CloudFrontDistributionID != "" {
|
||||
if d.cfg.DryRun {
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Printf("[DRY RUN] Would invalidate CloudFront CDN with ID %s\n", d.target.CloudFrontDistributionID)
|
||||
d.logger.Printf("[DRY RUN] Would invalidate CloudFront CDN with ID %s\n", d.target.CloudFrontDistributionID)
|
||||
}
|
||||
} else {
|
||||
jww.FEEDBACK.Println("Invalidating CloudFront CDN...")
|
||||
d.logger.Println("Invalidating CloudFront CDN...")
|
||||
if err := InvalidateCloudFront(ctx, d.target.CloudFrontDistributionID); err != nil {
|
||||
jww.FEEDBACK.Printf("Failed to invalidate CloudFront CDN: %v\n", err)
|
||||
d.logger.Printf("Failed to invalidate CloudFront CDN: %v\n", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -275,17 +280,17 @@ func (d *Deployer) Deploy(ctx context.Context) error {
|
|||
if d.target.GoogleCloudCDNOrigin != "" {
|
||||
if d.cfg.DryRun {
|
||||
if !d.quiet {
|
||||
jww.FEEDBACK.Printf("[DRY RUN] Would invalidate Google Cloud CDN with origin %s\n", d.target.GoogleCloudCDNOrigin)
|
||||
d.logger.Printf("[DRY RUN] Would invalidate Google Cloud CDN with origin %s\n", d.target.GoogleCloudCDNOrigin)
|
||||
}
|
||||
} else {
|
||||
jww.FEEDBACK.Println("Invalidating Google Cloud CDN...")
|
||||
d.logger.Println("Invalidating Google Cloud CDN...")
|
||||
if err := InvalidateGoogleCloudCDN(ctx, d.target.GoogleCloudCDNOrigin); err != nil {
|
||||
jww.FEEDBACK.Printf("Failed to invalidate Google Cloud CDN: %v\n", err)
|
||||
d.logger.Printf("Failed to invalidate Google Cloud CDN: %v\n", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
jww.FEEDBACK.Println("Success!")
|
||||
d.logger.Println("Success!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -300,8 +305,8 @@ func summarizeChanges(uploads []*fileToUpload, deletes []string) string {
|
|||
}
|
||||
|
||||
// doSingleUpload executes a single file upload.
|
||||
func doSingleUpload(ctx context.Context, bucket *blob.Bucket, upload *fileToUpload) error {
|
||||
jww.INFO.Printf("Uploading %v...\n", upload)
|
||||
func (d *Deployer) doSingleUpload(ctx context.Context, bucket *blob.Bucket, upload *fileToUpload) error {
|
||||
d.logger.Infof("Uploading %v...\n", upload)
|
||||
opts := &blob.WriterOptions{
|
||||
CacheControl: upload.Local.CacheControl(),
|
||||
ContentEncoding: upload.Local.ContentEncoding(),
|
||||
|
@ -479,7 +484,7 @@ func knownHiddenDirectory(name string) bool {
|
|||
|
||||
// walkLocal walks the source directory and returns a flat list of files,
|
||||
// using localFile.SlashPath as the map keys.
|
||||
func walkLocal(fs afero.Fs, matchers []*Matcher, include, exclude glob.Glob, mediaTypes media.Types) (map[string]*localFile, error) {
|
||||
func (d *Deployer) walkLocal(fs afero.Fs, matchers []*Matcher, include, exclude glob.Glob, mediaTypes media.Types) (map[string]*localFile, error) {
|
||||
retval := map[string]*localFile{}
|
||||
err := afero.Walk(fs, "", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
@ -509,11 +514,11 @@ func walkLocal(fs afero.Fs, matchers []*Matcher, include, exclude glob.Glob, med
|
|||
// Check include/exclude matchers.
|
||||
slashpath := filepath.ToSlash(path)
|
||||
if include != nil && !include.Match(slashpath) {
|
||||
jww.INFO.Printf(" dropping %q due to include\n", slashpath)
|
||||
d.logger.Infof(" dropping %q due to include\n", slashpath)
|
||||
return nil
|
||||
}
|
||||
if exclude != nil && exclude.Match(slashpath) {
|
||||
jww.INFO.Printf(" dropping %q due to exclude\n", slashpath)
|
||||
d.logger.Infof(" dropping %q due to exclude\n", slashpath)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -539,7 +544,7 @@ func walkLocal(fs afero.Fs, matchers []*Matcher, include, exclude glob.Glob, med
|
|||
}
|
||||
|
||||
// walkRemote walks the target bucket and returns a flat list.
|
||||
func walkRemote(ctx context.Context, bucket *blob.Bucket, include, exclude glob.Glob) (map[string]*blob.ListObject, error) {
|
||||
func (d *Deployer) walkRemote(ctx context.Context, bucket *blob.Bucket, include, exclude glob.Glob) (map[string]*blob.ListObject, error) {
|
||||
retval := map[string]*blob.ListObject{}
|
||||
iter := bucket.List(nil)
|
||||
for {
|
||||
|
@ -552,11 +557,11 @@ func walkRemote(ctx context.Context, bucket *blob.Bucket, include, exclude glob.
|
|||
}
|
||||
// Check include/exclude matchers.
|
||||
if include != nil && !include.Match(obj.Key) {
|
||||
jww.INFO.Printf(" remote dropping %q due to include\n", obj.Key)
|
||||
d.logger.Infof(" remote dropping %q due to include\n", obj.Key)
|
||||
continue
|
||||
}
|
||||
if exclude != nil && exclude.Match(obj.Key) {
|
||||
jww.INFO.Printf(" remote dropping %q due to exclude\n", obj.Key)
|
||||
d.logger.Infof(" remote dropping %q due to exclude\n", obj.Key)
|
||||
continue
|
||||
}
|
||||
// If the remote didn't give us an MD5, use remote attributes MD5, if that doesn't exist compute one.
|
||||
|
@ -629,7 +634,7 @@ func (u *fileToUpload) String() string {
|
|||
// findDiffs diffs localFiles vs remoteFiles to see what changes should be
|
||||
// applied to the remote target. It returns a slice of *fileToUpload and a
|
||||
// slice of paths for files to delete.
|
||||
func findDiffs(localFiles map[string]*localFile, remoteFiles map[string]*blob.ListObject, force bool) ([]*fileToUpload, []string) {
|
||||
func (d *Deployer) findDiffs(localFiles map[string]*localFile, remoteFiles map[string]*blob.ListObject, force bool) ([]*fileToUpload, []string) {
|
||||
var uploads []*fileToUpload
|
||||
var deletes []string
|
||||
|
||||
|
@ -680,10 +685,10 @@ func findDiffs(localFiles map[string]*localFile, remoteFiles map[string]*blob.Li
|
|||
reason = reasonNotFound
|
||||
}
|
||||
if upload {
|
||||
jww.DEBUG.Printf("%s needs to be uploaded: %v\n", path, reason)
|
||||
d.logger.Debugf("%s needs to be uploaded: %v\n", path, reason)
|
||||
uploads = append(uploads, &fileToUpload{lf, reason})
|
||||
} else {
|
||||
jww.DEBUG.Printf("%s exists at target and does not need to be uploaded", path)
|
||||
d.logger.Debugf("%s exists at target and does not need to be uploaded", path)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
|
@ -197,7 +198,8 @@ func TestFindDiffs(t *testing.T) {
|
|||
for _, r := range tc.Remote {
|
||||
remote[r.Key] = r
|
||||
}
|
||||
gotUpdates, gotDeletes := findDiffs(local, remote, tc.Force)
|
||||
d := newDeployer()
|
||||
gotUpdates, gotDeletes := d.findDiffs(local, remote, tc.Force)
|
||||
gotUpdates = applyOrdering(nil, gotUpdates)[0]
|
||||
sort.Slice(gotDeletes, func(i, j int) bool { return gotDeletes[i] < gotDeletes[j] })
|
||||
if diff := cmp.Diff(gotUpdates, tc.WantUpdates, cmpopts.IgnoreUnexported(localFile{})); diff != "" {
|
||||
|
@ -249,7 +251,8 @@ func TestWalkLocal(t *testing.T) {
|
|||
fd.Close()
|
||||
}
|
||||
}
|
||||
if got, err := walkLocal(fs, nil, nil, nil, media.DefaultTypes); err != nil {
|
||||
d := newDeployer()
|
||||
if got, err := d.walkLocal(fs, nil, nil, nil, media.DefaultTypes); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
expect := map[string]any{}
|
||||
|
@ -1026,3 +1029,9 @@ func verifyRemote(ctx context.Context, bucket *blob.Bucket, local []*fileData) (
|
|||
}
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
func newDeployer() *Deployer {
|
||||
return &Deployer{
|
||||
logger: loggers.NewDefault(),
|
||||
}
|
||||
}
|
||||
|
|
32
deps/deps.go
vendored
32
deps/deps.go
vendored
|
@ -3,12 +3,14 @@ package deps
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
|
@ -25,7 +27,6 @@ import (
|
|||
"github.com/gohugoio/hugo/source"
|
||||
"github.com/gohugoio/hugo/tpl"
|
||||
"github.com/spf13/afero"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
// Deps holds dependencies used by many.
|
||||
|
@ -36,9 +37,6 @@ type Deps struct {
|
|||
// The logger to use.
|
||||
Log loggers.Logger `json:"-"`
|
||||
|
||||
// Used to log errors that may repeat itself many times.
|
||||
LogDistinct loggers.Logger
|
||||
|
||||
ExecHelper *hexec.Exec
|
||||
|
||||
// The templates to use. This will usually implement the full tpl.TemplateManager.
|
||||
|
@ -117,15 +115,13 @@ func (d *Deps) Init() error {
|
|||
}
|
||||
|
||||
if d.Log == nil {
|
||||
d.Log = loggers.NewErrorLogger()
|
||||
}
|
||||
|
||||
if d.LogDistinct == nil {
|
||||
d.LogDistinct = helpers.NewDistinctLogger(d.Log)
|
||||
d.Log = loggers.NewDefault()
|
||||
}
|
||||
|
||||
if d.globalErrHandler == nil {
|
||||
d.globalErrHandler = &globalErrHandler{}
|
||||
d.globalErrHandler = &globalErrHandler{
|
||||
logger: d.Log,
|
||||
}
|
||||
}
|
||||
|
||||
if d.BuildState == nil {
|
||||
|
@ -228,6 +224,8 @@ func (d *Deps) Compile(prototype *Deps) error {
|
|||
}
|
||||
|
||||
type globalErrHandler struct {
|
||||
logger loggers.Logger
|
||||
|
||||
// Channel for some "hard to get to" build errors
|
||||
buildErrors chan error
|
||||
// Used to signal that the build is done.
|
||||
|
@ -246,8 +244,7 @@ func (e *globalErrHandler) SendError(err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
jww.ERROR.Println(err)
|
||||
e.logger.Errorln(err)
|
||||
}
|
||||
|
||||
func (e *globalErrHandler) StartErrorCollector() chan error {
|
||||
|
@ -312,9 +309,16 @@ func (d *Deps) Close() error {
|
|||
// on a global level, i.e. logging etc.
|
||||
// Nil values will be given default values.
|
||||
type DepsCfg struct {
|
||||
// The logger to use. Only set in some tests.
|
||||
// TODO(bep) get rid of this.
|
||||
TestLogger loggers.Logger
|
||||
|
||||
// The Logger to use.
|
||||
Logger loggers.Logger
|
||||
// The logging level to use.
|
||||
LogLevel logg.Level
|
||||
|
||||
// Where to write the logs.
|
||||
// Currently we typically write everything to stdout.
|
||||
LogOut io.Writer
|
||||
|
||||
// The file systems to use
|
||||
Fs *hugofs.Fs
|
||||
|
|
6
go.mod
6
go.mod
|
@ -16,6 +16,7 @@ require (
|
|||
github.com/bep/gowebp v0.2.0
|
||||
github.com/bep/helpers v0.4.0
|
||||
github.com/bep/lazycache v0.2.0
|
||||
github.com/bep/logg v0.2.0
|
||||
github.com/bep/mclib v1.20400.20402
|
||||
github.com/bep/overlayfs v0.6.0
|
||||
github.com/bep/simplecobra v0.3.2
|
||||
|
@ -25,6 +26,7 @@ require (
|
|||
github.com/disintegration/gift v1.2.1
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/evanw/esbuild v0.18.3
|
||||
github.com/fatih/color v1.15.0
|
||||
github.com/fortytw2/leaktest v1.3.0
|
||||
github.com/frankban/quicktest v1.14.5
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
|
@ -58,7 +60,6 @@ require (
|
|||
github.com/spf13/cast v1.5.1
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/fsync v0.9.0
|
||||
github.com/spf13/jwalterweatherman v1.1.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/tdewolff/minify/v2 v2.12.6
|
||||
github.com/tdewolff/parse/v2 v2.6.6
|
||||
|
@ -109,6 +110,7 @@ require (
|
|||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.3 // indirect
|
||||
github.com/aws/smithy-go v1.13.5 // indirect
|
||||
github.com/bep/clocks v0.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
|
@ -129,11 +131,13 @@ require (
|
|||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.4 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.10.0 // indirect
|
||||
|
|
12
go.sum
12
go.sum
|
@ -612,6 +612,8 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
|||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bep/clock v0.3.0 h1:vfOA6+wVb6pPQEiXow9f/too92vNTLe9MuwO13PfI0M=
|
||||
github.com/bep/clock v0.3.0/go.mod h1:6Gz2lapnJ9vxpvPxQ2u6FcXFRoj4kkiqQ6pm0ERZlwk=
|
||||
github.com/bep/clocks v0.5.0 h1:hhvKVGLPQWRVsBP/UB7ErrHYIO42gINVbvqxvYTPVps=
|
||||
github.com/bep/clocks v0.5.0/go.mod h1:SUq3q+OOq41y2lRQqH5fsOoxN8GbxSiT6jvoVVLCVhU=
|
||||
github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo=
|
||||
github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
|
||||
github.com/bep/gitmap v1.1.2 h1:zk04w1qc1COTZPPYWDQHvns3y1afOsdRfraFQ3qI840=
|
||||
|
@ -630,6 +632,8 @@ github.com/bep/helpers v0.4.0 h1:ab9veaAiWY4ST48Oxp5usaqivDmYdB744fz+tcZ3Ifs=
|
|||
github.com/bep/helpers v0.4.0/go.mod h1:/QpHdmcPagDw7+RjkLFCvnlUc8lQ5kg4KDrEkb2Yyco=
|
||||
github.com/bep/lazycache v0.2.0 h1:HKrlZTrDxHIrNKqmnurH42ryxkngCMYLfBpyu40VcwY=
|
||||
github.com/bep/lazycache v0.2.0/go.mod h1:xUIsoRD824Vx0Q/n57+ZO7kmbEhMBOnTjM/iPixNGbg=
|
||||
github.com/bep/logg v0.2.0 h1:EWKB04ea/K/V0xd/7O6x5q+1l+Grub+9N48YMcevtF4=
|
||||
github.com/bep/logg v0.2.0/go.mod h1:Ccp9yP3wbR1mm++Kpxet91hAZBEQgmWgFgnXX3GkIV0=
|
||||
github.com/bep/mclib v1.20400.20402 h1:olpCE2WSPpOAbFE1R4hnftSEmQ34+xzy2HRzd0m69rA=
|
||||
github.com/bep/mclib v1.20400.20402/go.mod h1:pkrk9Kyfqg34Uj6XlDq9tdEFJBiL1FvCoCgVKRzw1EY=
|
||||
github.com/bep/overlayfs v0.6.0 h1:sgLcq/qtIzbaQNl2TldGXOkHvqeZB025sPvHOQL+DYo=
|
||||
|
@ -916,6 +920,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
|
|||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
|
@ -1496,6 +1502,8 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
|
|||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
|
@ -1505,6 +1513,7 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME
|
|||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
|
@ -1692,6 +1701,7 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
|
|||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
|
@ -1840,7 +1850,6 @@ github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRM
|
|||
github.com/spf13/fsync v0.9.0 h1:f9CEt3DOB2mnHxZaftmEOFWjABEvKM/xpf3cUwJrGOY=
|
||||
github.com/spf13/fsync v0.9.0/go.mod h1:fNtJEfG3HiltN3y4cPOz6MLjos9+2pIEqLIgszqhp/0=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
|
@ -2441,6 +2450,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
|
@ -24,13 +24,11 @@ import (
|
|||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
|
||||
|
@ -254,143 +252,6 @@ func compareStringSlices(a, b []string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// DistinctLogger ignores duplicate log statements.
|
||||
type DistinctLogger struct {
|
||||
loggers.Logger
|
||||
sync.RWMutex
|
||||
m map[string]bool
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Reset() {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.m = make(map[string]bool)
|
||||
}
|
||||
|
||||
// Println will log the string returned from fmt.Sprintln given the arguments,
|
||||
// but not if it has been logged before.
|
||||
func (l *DistinctLogger) Println(v ...any) {
|
||||
// fmt.Sprint doesn't add space between string arguments
|
||||
logStatement := strings.TrimSpace(fmt.Sprintln(v...))
|
||||
l.printIfNotPrinted("println", logStatement, func() {
|
||||
l.Logger.Println(logStatement)
|
||||
})
|
||||
}
|
||||
|
||||
// Printf will log the string returned from fmt.Sprintf given the arguments,
|
||||
// but not if it has been logged before.
|
||||
func (l *DistinctLogger) Printf(format string, v ...any) {
|
||||
logStatement := fmt.Sprintf(format, v...)
|
||||
l.printIfNotPrinted("printf", logStatement, func() {
|
||||
l.Logger.Printf(format, v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Debugf(format string, v ...any) {
|
||||
logStatement := fmt.Sprintf(format, v...)
|
||||
l.printIfNotPrinted("debugf", logStatement, func() {
|
||||
l.Logger.Debugf(format, v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Debugln(v ...any) {
|
||||
logStatement := fmt.Sprint(v...)
|
||||
l.printIfNotPrinted("debugln", logStatement, func() {
|
||||
l.Logger.Debugln(v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Infof(format string, v ...any) {
|
||||
logStatement := fmt.Sprintf(format, v...)
|
||||
l.printIfNotPrinted("info", logStatement, func() {
|
||||
l.Logger.Infof(format, v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Infoln(v ...any) {
|
||||
logStatement := fmt.Sprint(v...)
|
||||
l.printIfNotPrinted("infoln", logStatement, func() {
|
||||
l.Logger.Infoln(v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Warnf(format string, v ...any) {
|
||||
logStatement := fmt.Sprintf(format, v...)
|
||||
l.printIfNotPrinted("warnf", logStatement, func() {
|
||||
l.Logger.Warnf(format, v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Warnln(v ...any) {
|
||||
logStatement := fmt.Sprint(v...)
|
||||
l.printIfNotPrinted("warnln", logStatement, func() {
|
||||
l.Logger.Warnln(v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Errorf(format string, v ...any) {
|
||||
logStatement := fmt.Sprint(v...)
|
||||
l.printIfNotPrinted("errorf", logStatement, func() {
|
||||
l.Logger.Errorf(format, v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) Errorln(v ...any) {
|
||||
logStatement := fmt.Sprint(v...)
|
||||
l.printIfNotPrinted("errorln", logStatement, func() {
|
||||
l.Logger.Errorln(v...)
|
||||
})
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) hasPrinted(key string) bool {
|
||||
l.RLock()
|
||||
defer l.RUnlock()
|
||||
_, found := l.m[key]
|
||||
return found
|
||||
}
|
||||
|
||||
func (l *DistinctLogger) printIfNotPrinted(level, logStatement string, print func()) {
|
||||
key := level + logStatement
|
||||
if l.hasPrinted(key) {
|
||||
return
|
||||
}
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
l.m[key] = true // Placing this after print() can cause duplicate warning entries to be logged when --panicOnWarning is true.
|
||||
print()
|
||||
|
||||
}
|
||||
|
||||
// NewDistinctErrorLogger creates a new DistinctLogger that logs ERRORs
|
||||
func NewDistinctErrorLogger() loggers.Logger {
|
||||
return &DistinctLogger{m: make(map[string]bool), Logger: loggers.NewErrorLogger()}
|
||||
}
|
||||
|
||||
// NewDistinctLogger creates a new DistinctLogger that logs to the provided logger.
|
||||
func NewDistinctLogger(logger loggers.Logger) loggers.Logger {
|
||||
return &DistinctLogger{m: make(map[string]bool), Logger: logger}
|
||||
}
|
||||
|
||||
// NewDistinctWarnLogger creates a new DistinctLogger that logs WARNs
|
||||
func NewDistinctWarnLogger() loggers.Logger {
|
||||
return &DistinctLogger{m: make(map[string]bool), Logger: loggers.NewWarningLogger()}
|
||||
}
|
||||
|
||||
var (
|
||||
// DistinctErrorLog can be used to avoid spamming the logs with errors.
|
||||
DistinctErrorLog = NewDistinctErrorLogger()
|
||||
|
||||
// DistinctWarnLog can be used to avoid spamming the logs with warnings.
|
||||
DistinctWarnLog = NewDistinctWarnLogger()
|
||||
)
|
||||
|
||||
// InitLoggers resets the global distinct loggers.
|
||||
func InitLoggers() {
|
||||
DistinctErrorLog.Reset()
|
||||
DistinctWarnLog.Reset()
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
@ -398,13 +259,9 @@ func InitLoggers() {
|
|||
// plenty of time to fix their templates.
|
||||
func Deprecated(item, alternative string, err bool) {
|
||||
if err {
|
||||
DistinctErrorLog.Errorf("%s is deprecated and will be removed in Hugo %s. %s", item, hugo.CurrentVersion.Next().ReleaseVersion(), alternative)
|
||||
loggers.Log().Errorf("%s is deprecated and will be removed in Hugo %s. %s", item, hugo.CurrentVersion.Next().ReleaseVersion(), alternative)
|
||||
} else {
|
||||
var warnPanicMessage string
|
||||
if !loggers.PanicOnWarning.Load() {
|
||||
warnPanicMessage = "\n\nRe-run Hugo with the flag --panicOnWarning to get a better error message."
|
||||
}
|
||||
DistinctWarnLog.Warnf("%s is deprecated and will be removed in a future release. %s%s", item, alternative, warnPanicMessage)
|
||||
loggers.Log().Warnf("%s is deprecated and will be removed in a future release. %s%s", item, alternative)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,7 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
|
@ -55,60 +53,6 @@ func TestResolveMarkup(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDistinctLoggerDoesNotLockOnWarningPanic(t *testing.T) {
|
||||
// Testing to make sure logger mutex doesn't lock if warnings cause panics.
|
||||
// func Warnf() of DistinctLogger is defined in general.go
|
||||
l := helpers.NewDistinctLogger(loggers.NewWarningLogger())
|
||||
|
||||
// Set PanicOnWarning to true to reproduce issue 9380
|
||||
// Ensure global variable loggers.PanicOnWarning is reset to old value after test
|
||||
if !loggers.PanicOnWarning.Load() {
|
||||
loggers.PanicOnWarning.Store(true)
|
||||
defer func() {
|
||||
loggers.PanicOnWarning.Store(false)
|
||||
}()
|
||||
}
|
||||
|
||||
// Establish timeout in case a lock occurs:
|
||||
timeIsUp := make(chan bool)
|
||||
timeOutSeconds := 1
|
||||
go func() {
|
||||
time.Sleep(time.Second * time.Duration(timeOutSeconds))
|
||||
timeIsUp <- true
|
||||
}()
|
||||
|
||||
// Attempt to run multiple logging threads in parallel
|
||||
counterC := make(chan int)
|
||||
goroutines := 5
|
||||
|
||||
for i := 0; i < goroutines; i++ {
|
||||
go func() {
|
||||
defer func() {
|
||||
// Intentional panic successfully recovered - notify counter channel
|
||||
recover()
|
||||
counterC <- 1
|
||||
}()
|
||||
|
||||
l.Warnf("Placeholder template message: %v", "In this test, logging a warning causes a panic.")
|
||||
}()
|
||||
}
|
||||
|
||||
// All goroutines should complete before timeout
|
||||
var counter int
|
||||
for {
|
||||
select {
|
||||
case <-counterC:
|
||||
counter++
|
||||
if counter == goroutines {
|
||||
return
|
||||
}
|
||||
case <-timeIsUp:
|
||||
t.Errorf("Unable to log warnings with --panicOnWarning within alloted time of: %v seconds. Investigate possible mutex locking on panic in distinct warning logger.", timeOutSeconds)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirstUpper(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
in string
|
||||
|
|
|
@ -23,7 +23,7 @@ func newTestPathSpecFromCfgAndLang(cfg config.Provider, lang string) *helpers.Pa
|
|||
}
|
||||
}
|
||||
fs := hugofs.NewFrom(mfs, conf.BaseConfig())
|
||||
ps, err := helpers.NewPathSpec(fs, conf, loggers.NewErrorLogger())
|
||||
ps, err := helpers.NewPathSpec(fs, conf, loggers.NewDefault())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func newTestPathSpec(configKeyValues ...any) *helpers.PathSpec {
|
|||
func newTestContentSpec(cfg config.Provider) *helpers.ContentSpec {
|
||||
fs := afero.NewMemMapFs()
|
||||
conf := testconfig.GetTestConfig(fs, cfg)
|
||||
spec, err := helpers.NewContentSpec(conf, loggers.NewErrorLogger(), fs, nil)
|
||||
spec, err := helpers.NewContentSpec(conf, loggers.NewDefault(), fs, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/htesting"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
|
@ -64,11 +64,11 @@ func TestNoSymlinkFs(t *testing.T) {
|
|||
blogDir := filepath.Join(workDir, "blog")
|
||||
blogFile1 := filepath.Join(blogDir, "a.txt")
|
||||
|
||||
logger := loggers.NewWarningLogger()
|
||||
logger := loggers.NewDefault()
|
||||
|
||||
for _, bfs := range []afero.Fs{NewBaseFileDecorator(Os), Os} {
|
||||
for _, allowFiles := range []bool{false, true} {
|
||||
logger.LogCounters().WarnCounter.Reset()
|
||||
logger.Reset()
|
||||
fs := NewNoSymlinkFs(bfs, logger, allowFiles)
|
||||
ls := fs.(afero.Lstater)
|
||||
symlinkedDir := filepath.Join(workDir, "symlinkdedir")
|
||||
|
@ -139,7 +139,7 @@ func TestNoSymlinkFs(t *testing.T) {
|
|||
_, err = f.Readdir(-1)
|
||||
c.Assert(err, qt.IsNil)
|
||||
f.Close()
|
||||
c.Assert(logger.LogCounters().WarnCounter.Count(), qt.Equals, uint64(1))
|
||||
c.Assert(logger.LoggCount(logg.LevelWarn), qt.Equals, 1)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ func NewWalkway(cfg WalkwayConfig) *Walkway {
|
|||
|
||||
logger := cfg.Logger
|
||||
if logger == nil {
|
||||
logger = loggers.NewWarningLogger()
|
||||
logger = loggers.NewDefault()
|
||||
}
|
||||
|
||||
return &Walkway{
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/output"
|
||||
"github.com/gohugoio/hugo/publisher"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
|
|
|
@ -18,9 +18,8 @@ import (
|
|||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
)
|
||||
|
||||
const pageWithAlias = `---
|
||||
|
@ -117,7 +116,7 @@ func TestAliasTemplate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTargetPathHTMLRedirectAlias(t *testing.T) {
|
||||
h := newAliasHandler(nil, loggers.NewErrorLogger(), false)
|
||||
h := newAliasHandler(nil, loggers.NewDefault(), false)
|
||||
|
||||
errIsNilForThisOS := runtime.GOOS != "windows"
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/config/allconfig"
|
||||
|
||||
|
@ -933,7 +934,7 @@ LanguageCode: {{ eq site.LanguageCode site.Language.LanguageCode }}|{{ site.Lang
|
|||
).Build()
|
||||
|
||||
{
|
||||
b.Assert(b.H.Log.LogCounters().WarnCounter.Count(), qt.Equals, uint64(2))
|
||||
b.Assert(b.H.Log.LoggCount(logg.LevelWarn), qt.Equals, 1)
|
||||
}
|
||||
b.AssertFileContent("public/index.html", `
|
||||
AllPages: 4|
|
||||
|
|
|
@ -29,9 +29,9 @@ import (
|
|||
"github.com/gohugoio/hugo/hugofs/glob"
|
||||
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/types"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/rogpeppe/go-internal/lockedfile"
|
||||
|
||||
"github.com/gohugoio/hugo/hugofs/files"
|
||||
|
@ -471,7 +471,7 @@ var counter int
|
|||
func NewBase(p *paths.Paths, logger loggers.Logger, options ...func(*BaseFs) error) (*BaseFs, error) {
|
||||
fs := p.Fs
|
||||
if logger == nil {
|
||||
logger = loggers.NewWarningLogger()
|
||||
logger = loggers.NewDefault()
|
||||
}
|
||||
|
||||
publishFs := hugofs.NewBaseFileDecorator(fs.PublishDir)
|
||||
|
|
|
@ -22,16 +22,16 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/modules/npm"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
|
||||
"github.com/gohugoio/hugo/hugofs/files"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/htesting"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
@ -646,14 +646,14 @@ min_version = 0.55.0
|
|||
|
||||
`)
|
||||
|
||||
logger := loggers.NewWarningLogger()
|
||||
logger := loggers.NewDefault()
|
||||
b.WithLogger(logger)
|
||||
|
||||
b.Build(BuildCfg{})
|
||||
|
||||
c := qt.New(t)
|
||||
|
||||
c.Assert(logger.LogCounters().WarnCounter.Count(), qt.Equals, uint64(3))
|
||||
c.Assert(logger.LoggCount(logg.LevelWarn), qt.Equals, 3)
|
||||
}
|
||||
|
||||
func TestModulesSymlinks(t *testing.T) {
|
||||
|
@ -727,7 +727,7 @@ weight = 2
|
|||
`
|
||||
|
||||
b := newTestSitesBuilder(t).WithNothingAdded().WithWorkingDir(workingDir)
|
||||
b.WithLogger(loggers.NewErrorLogger())
|
||||
b.WithLogger(loggers.NewDefault())
|
||||
b.Fs = fs
|
||||
|
||||
b.WithConfigFile("toml", config)
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/config/allconfig"
|
||||
"github.com/gohugoio/hugo/hugofs/glob"
|
||||
|
||||
|
@ -42,7 +43,6 @@ import (
|
|||
"github.com/gohugoio/hugo/source"
|
||||
|
||||
"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/lazy"
|
||||
|
@ -265,7 +265,7 @@ func (h *HugoSites) NumLogErrors() int {
|
|||
if h == nil {
|
||||
return 0
|
||||
}
|
||||
return int(h.Log.LogCounters().ErrorCounter.Count())
|
||||
return h.Log.LoggCount(logg.LevelError)
|
||||
}
|
||||
|
||||
func (h *HugoSites) PrintProcessingStats(w io.Writer) {
|
||||
|
@ -352,10 +352,8 @@ func (h *HugoSites) reset(config *BuildCfg) {
|
|||
// resetLogs resets the log counters etc. Used to do a new build on the same sites.
|
||||
func (h *HugoSites) resetLogs() {
|
||||
h.Log.Reset()
|
||||
loggers.GlobalErrorCounter.Reset()
|
||||
for _, s := range h.Sites {
|
||||
s.Deps.Log.Reset()
|
||||
s.Deps.LogDistinct.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/langs"
|
||||
"github.com/gohugoio/hugo/publisher"
|
||||
|
||||
|
@ -65,6 +66,8 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
|
|||
defer unlock()
|
||||
}
|
||||
|
||||
infol := h.Log.InfoCommand("build")
|
||||
|
||||
errCollector := h.StartErrorCollector()
|
||||
errs := make(chan error)
|
||||
|
||||
|
@ -120,11 +123,11 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if err := h.process(conf, init, events...); err != nil {
|
||||
if err := h.process(infol, conf, init, events...); err != nil {
|
||||
return fmt.Errorf("process: %w", err)
|
||||
}
|
||||
|
||||
if err := h.assemble(conf); err != nil {
|
||||
if err := h.assemble(infol, conf); err != nil {
|
||||
return fmt.Errorf("assemble: %w", err)
|
||||
}
|
||||
|
||||
|
@ -137,10 +140,10 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
|
|||
}
|
||||
|
||||
if prepareErr == nil {
|
||||
if err := h.render(conf); err != nil {
|
||||
if err := h.render(infol, conf); err != nil {
|
||||
h.SendError(fmt.Errorf("render: %w", err))
|
||||
}
|
||||
if err := h.postProcess(); err != nil {
|
||||
if err := h.postProcess(infol); err != nil {
|
||||
h.SendError(fmt.Errorf("postProcess: %w", err))
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +167,7 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
|
|||
return err
|
||||
}
|
||||
|
||||
errorCount := h.Log.LogCounters().ErrorCounter.Count()
|
||||
errorCount := h.Log.LoggCount(logg.LevelError)
|
||||
if errorCount > 0 {
|
||||
return fmt.Errorf("logged %d error(s)", errorCount)
|
||||
}
|
||||
|
@ -195,13 +198,12 @@ func (h *HugoSites) initRebuild(config *BuildCfg) error {
|
|||
|
||||
h.reset(config)
|
||||
h.resetLogs()
|
||||
helpers.InitLoggers()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HugoSites) process(config *BuildCfg, init func(config *BuildCfg) error, events ...fsnotify.Event) error {
|
||||
defer h.timeTrack(time.Now(), "process")
|
||||
func (h *HugoSites) process(l logg.LevelLogger, config *BuildCfg, init func(config *BuildCfg) error, events ...fsnotify.Event) error {
|
||||
defer h.timeTrack(l, time.Now(), "process")
|
||||
|
||||
// We should probably refactor the Site and pull up most of the logic from there to here,
|
||||
// but that seems like a daunting task.
|
||||
|
@ -218,8 +220,8 @@ func (h *HugoSites) process(config *BuildCfg, init func(config *BuildCfg) error,
|
|||
return firstSite.process(*config)
|
||||
}
|
||||
|
||||
func (h *HugoSites) assemble(bcfg *BuildCfg) error {
|
||||
defer h.timeTrack(time.Now(), "assemble")
|
||||
func (h *HugoSites) assemble(l logg.LevelLogger, bcfg *BuildCfg) error {
|
||||
defer h.timeTrack(l, time.Now(), "assemble")
|
||||
|
||||
if !bcfg.whatChanged.source {
|
||||
return nil
|
||||
|
@ -236,13 +238,13 @@ func (h *HugoSites) assemble(bcfg *BuildCfg) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (h *HugoSites) timeTrack(start time.Time, name string) {
|
||||
func (h *HugoSites) timeTrack(l logg.LevelLogger, start time.Time, name string) {
|
||||
elapsed := time.Since(start)
|
||||
h.Log.Infof("%s in %v ms\n", name, int(1000*elapsed.Seconds()))
|
||||
l.WithField("step", name).WithField("duration", elapsed).Logf("running")
|
||||
}
|
||||
|
||||
func (h *HugoSites) render(config *BuildCfg) error {
|
||||
defer h.timeTrack(time.Now(), "render")
|
||||
func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
|
||||
defer h.timeTrack(l, time.Now(), "render")
|
||||
if _, err := h.init.layouts.Do(context.Background()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -312,8 +314,8 @@ func (h *HugoSites) render(config *BuildCfg) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (h *HugoSites) postProcess() error {
|
||||
defer h.timeTrack(time.Now(), "postProcess")
|
||||
func (h *HugoSites) postProcess(l logg.LevelLogger) error {
|
||||
defer h.timeTrack(l, time.Now(), "postProcess")
|
||||
|
||||
// Make sure to write any build stats to disk first so it's available
|
||||
// to the post processors.
|
||||
|
|
|
@ -1394,7 +1394,7 @@ other = %q
|
|||
}
|
||||
|
||||
func TestRebuildOnAssetChange(t *testing.T) {
|
||||
b := newTestSitesBuilder(t).Running().WithLogger(loggers.NewInfoLogger())
|
||||
b := newTestSitesBuilder(t).Running().WithLogger(loggers.NewDefault())
|
||||
b.WithTemplatesAdded("index.html", `
|
||||
{{ (resources.Get "data.json").Content }}
|
||||
`)
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"sync"
|
||||
"testing"
|
||||
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"github.com/bep/logg"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
|
@ -292,11 +292,9 @@ func (s *IntegrationTestBuilder) initBuilder() error {
|
|||
}
|
||||
|
||||
if s.Cfg.LogLevel == 0 {
|
||||
s.Cfg.LogLevel = jww.LevelWarn
|
||||
s.Cfg.LogLevel = logg.LevelWarn
|
||||
}
|
||||
|
||||
logger := loggers.NewBasicLoggerForWriter(s.Cfg.LogLevel, &s.logBuff)
|
||||
|
||||
isBinaryRe := regexp.MustCompile(`^(.*)(\.png|\.jpg)$`)
|
||||
|
||||
const dataSourceFilenamePrefix = "sourcefilename:"
|
||||
|
@ -350,7 +348,7 @@ func (s *IntegrationTestBuilder) initBuilder() error {
|
|||
Flags: flags,
|
||||
ConfigDir: configDir,
|
||||
Fs: afs,
|
||||
Logger: logger,
|
||||
Logger: loggers.NewDefault(),
|
||||
Environ: s.Cfg.Environ,
|
||||
},
|
||||
)
|
||||
|
@ -364,7 +362,7 @@ func (s *IntegrationTestBuilder) initBuilder() error {
|
|||
|
||||
s.Assert(err, qt.IsNil)
|
||||
|
||||
depsCfg := deps.DepsCfg{Configs: res, Fs: fs, Logger: logger}
|
||||
depsCfg := deps.DepsCfg{Configs: res, Fs: fs, LogLevel: s.Cfg.LogLevel, LogOut: &s.logBuff}
|
||||
sites, err := NewHugoSites(depsCfg)
|
||||
if err != nil {
|
||||
initErr = err
|
||||
|
@ -528,7 +526,7 @@ type IntegrationTestConfig struct {
|
|||
// Will print the log buffer after the build
|
||||
Verbose bool
|
||||
|
||||
LogLevel jww.Threshold
|
||||
LogLevel logg.Level
|
||||
|
||||
// Whether it needs the real file system (e.g. for js.Build tests).
|
||||
NeedsOsFS bool
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/hugofs/files"
|
||||
|
||||
"github.com/gohugoio/hugo/htesting"
|
||||
|
@ -39,7 +38,7 @@ func TestMountFilters(t *testing.T) {
|
|||
for _, component := range files.ComponentFolders {
|
||||
b.Assert(os.MkdirAll(filepath.Join(workingDir, component), 0777), qt.IsNil)
|
||||
}
|
||||
b.WithWorkingDir(workingDir).WithLogger(loggers.NewInfoLogger())
|
||||
b.WithWorkingDir(workingDir).WithLogger(loggers.NewDefault())
|
||||
b.WithConfigFile("toml", fmt.Sprintf(`
|
||||
workingDir = %q
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ func newPageFromMeta(
|
|||
meta map[string]any,
|
||||
metaProvider *pageMeta) (*pageState, error) {
|
||||
if metaProvider.f == nil {
|
||||
metaProvider.f = page.NewZeroFile(metaProvider.s.LogDistinct)
|
||||
metaProvider.f = page.NewZeroFile(metaProvider.s.Log)
|
||||
}
|
||||
|
||||
ps, err := newPageBase(metaProvider)
|
||||
|
|
|
@ -17,7 +17,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -36,7 +35,6 @@ import (
|
|||
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
"github.com/gohugoio/hugo/resources/resource"
|
||||
"github.com/spf13/jwalterweatherman"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
|
@ -739,7 +737,7 @@ Here is the last report for commits in the year 2016. It covers hrev50718-hrev50
|
|||
func TestRenderStringForRegularPageTranslations(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
b := newTestSitesBuilder(t)
|
||||
b.WithLogger(loggers.NewBasicLoggerForWriter(jwalterweatherman.LevelError, os.Stderr))
|
||||
b.WithLogger(loggers.NewDefault())
|
||||
|
||||
b.WithConfigFile("toml",
|
||||
`baseurl = "https://example.org/"
|
||||
|
@ -800,7 +798,7 @@ home = ["HTML", "JSON"]`)
|
|||
// Issue 8919
|
||||
func TestContentProviderWithCustomOutputFormat(t *testing.T) {
|
||||
b := newTestSitesBuilder(t)
|
||||
b.WithLogger(loggers.NewBasicLoggerForWriter(jwalterweatherman.LevelDebug, os.Stderr))
|
||||
b.WithLogger(loggers.NewDefault())
|
||||
b.WithConfigFile("toml", `baseURL = 'http://example.org/'
|
||||
title = 'My New Hugo Site'
|
||||
|
||||
|
@ -1437,7 +1435,7 @@ Content:{{ .Content }}
|
|||
|
||||
// https://github.com/gohugoio/hugo/issues/5781
|
||||
func TestPageWithZeroFile(t *testing.T) {
|
||||
newTestSitesBuilder(t).WithLogger(loggers.NewWarningLogger()).WithSimpleConfigFile().
|
||||
newTestSitesBuilder(t).WithLogger(loggers.NewDefault()).WithSimpleConfigFile().
|
||||
WithTemplatesAdded("index.html", "{{ .File.Filename }}{{ with .File }}{{ .Dir }}{{ end }}").Build(BuildCfg{})
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -31,7 +34,6 @@ import (
|
|||
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
|
||||
"github.com/gohugoio/hugo/htesting"
|
||||
|
@ -93,7 +95,7 @@ func TestPageBundlerSiteRegular(t *testing.T) {
|
|||
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
b := newTestSitesBuilderFromDepsCfg(c, deps.DepsCfg{Logger: loggers.NewErrorLogger(), Fs: fs, Configs: configs}).WithNothingAdded()
|
||||
b := newTestSitesBuilderFromDepsCfg(c, deps.DepsCfg{Fs: fs, Configs: configs}).WithNothingAdded()
|
||||
|
||||
b.Build(BuildCfg{})
|
||||
|
||||
|
@ -1044,7 +1046,7 @@ title: %q
|
|||
}
|
||||
|
||||
b := newTestSitesBuilder(t).WithConfigFile("toml", config)
|
||||
b.WithLogger(loggers.NewWarningLogger())
|
||||
b.WithLogger(loggers.NewDefault())
|
||||
|
||||
b.WithTemplates("_default/list.html", `{{ range .Site.Pages }}
|
||||
{{ .Kind }}|{{ .Path }}|{{ with .CurrentSection }}CurrentSection: {{ .Path }}{{ end }}|{{ .RelPermalink }}{{ end }}
|
||||
|
@ -1215,7 +1217,7 @@ title: %q
|
|||
}
|
||||
|
||||
b := newTestSitesBuilder(t).WithConfigFile("toml", config)
|
||||
b.WithLogger(loggers.NewWarningLogger())
|
||||
b.WithLogger(loggers.NewDefault())
|
||||
|
||||
b.WithTemplates("_default/single.html", `{{ range .Resources }}
|
||||
{{ .ResourceType }}|{{ .Title }}|
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"reflect"
|
||||
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
|
||||
"github.com/gohugoio/hugo/parser/pageparser"
|
||||
|
@ -29,7 +30,6 @@ import (
|
|||
|
||||
"github.com/gohugoio/hugo/source"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
|
|
@ -53,7 +53,7 @@ func TestPagesCapture(t *testing.T) {
|
|||
t.Run("Collect", func(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
proc := &testPagesCollectorProcessor{}
|
||||
coll := newPagesCollector(sourceSpec, nil, loggers.NewErrorLogger(), nil, proc)
|
||||
coll := newPagesCollector(sourceSpec, nil, loggers.NewDefault(), nil, proc)
|
||||
c.Assert(coll.Collect(), qt.IsNil)
|
||||
// 2 bundles, 3 pages.
|
||||
c.Assert(len(proc.items), qt.Equals, 5)
|
||||
|
|
|
@ -16,6 +16,7 @@ package hugolib
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
)
|
||||
|
@ -80,13 +81,13 @@ func TestRenderStringOnListPage(t *testing.T) {
|
|||
// Issue 9433
|
||||
func TestRenderStringOnPageNotBackedByAFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
logger := loggers.NewWarningLogger()
|
||||
logger := loggers.NewDefault()
|
||||
b := newTestSitesBuilder(t).WithLogger(logger).WithConfigFile("toml", `
|
||||
disableKinds = ["page", "section", "taxonomy", "term"]
|
||||
`)
|
||||
b.WithTemplates("index.html", `{{ .RenderString "**Hello**" }}`).WithContent("p1.md", "")
|
||||
b.BuildE(BuildCfg{})
|
||||
b.Assert(int(logger.LogCounters().WarnCounter.Count()), qt.Equals, 0)
|
||||
b.Assert(logger.LoggCount(logg.LevelWarn), qt.Equals, 0)
|
||||
}
|
||||
|
||||
func TestRenderStringWithShortcode(t *testing.T) {
|
||||
|
|
|
@ -588,7 +588,7 @@ XML: {{ $xml.body }}
|
|||
}
|
||||
t.Parallel()
|
||||
|
||||
b := newTestSitesBuilder(t).WithLogger(loggers.NewErrorLogger())
|
||||
b := newTestSitesBuilder(t).WithLogger(loggers.NewDefault())
|
||||
b.WithContent("_index.md", `
|
||||
---
|
||||
title: Home
|
||||
|
|
|
@ -17,7 +17,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
"net/url"
|
||||
"path"
|
||||
|
@ -27,6 +26,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
"github.com/gohugoio/hugo/common/htime"
|
||||
"github.com/gohugoio/hugo/common/hugio"
|
||||
|
@ -285,7 +285,7 @@ func (s *Site) isEnabled(kind string) bool {
|
|||
type siteRefLinker struct {
|
||||
s *Site
|
||||
|
||||
errorLogger *log.Logger
|
||||
errorLogger logg.LevelLogger
|
||||
notFoundURL string
|
||||
}
|
||||
|
||||
|
@ -302,11 +302,11 @@ func newSiteRefLinker(s *Site) (siteRefLinker, error) {
|
|||
|
||||
func (s siteRefLinker) logNotFound(ref, what string, p page.Page, position text.Position) {
|
||||
if position.IsValid() {
|
||||
s.errorLogger.Printf("[%s] REF_NOT_FOUND: Ref %q: %s: %s", s.s.Lang(), ref, position.String(), what)
|
||||
s.errorLogger.Logf("[%s] REF_NOT_FOUND: Ref %q: %s: %s", s.s.Lang(), ref, position.String(), what)
|
||||
} else if p == nil {
|
||||
s.errorLogger.Printf("[%s] REF_NOT_FOUND: Ref %q: %s", s.s.Lang(), ref, what)
|
||||
s.errorLogger.Logf("[%s] REF_NOT_FOUND: Ref %q: %s", s.s.Lang(), ref, what)
|
||||
} else {
|
||||
s.errorLogger.Printf("[%s] REF_NOT_FOUND: Ref %q from page %q: %s", s.s.Lang(), ref, p.Pathc(), what)
|
||||
s.errorLogger.Logf("[%s] REF_NOT_FOUND: Ref %q from page %q: %s", s.s.Lang(), ref, p.Pathc(), what)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,9 +507,6 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
|
|||
i18nChanged bool
|
||||
|
||||
sourceFilesChanged = make(map[string]bool)
|
||||
|
||||
// prevent spamming the log on changes
|
||||
logger = helpers.NewDistinctErrorLogger()
|
||||
)
|
||||
|
||||
var cacheBusters []func(string) bool
|
||||
|
@ -531,7 +528,7 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
|
|||
|
||||
switch id.Type {
|
||||
case files.ComponentFolderContent:
|
||||
logger.Println("Source changed", ev)
|
||||
s.Log.Println("Source changed", ev)
|
||||
sourceChanged = append(sourceChanged, ev)
|
||||
case files.ComponentFolderLayouts:
|
||||
tmplChanged = true
|
||||
|
@ -539,16 +536,16 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
|
|||
tmplAdded = true
|
||||
}
|
||||
if tmplAdded {
|
||||
logger.Println("Template added", ev)
|
||||
s.Log.Println("Template added", ev)
|
||||
} else {
|
||||
logger.Println("Template changed", ev)
|
||||
s.Log.Println("Template changed", ev)
|
||||
}
|
||||
|
||||
case files.ComponentFolderData:
|
||||
logger.Println("Data changed", ev)
|
||||
s.Log.Println("Data changed", ev)
|
||||
dataChanged = true
|
||||
case files.ComponentFolderI18n:
|
||||
logger.Println("i18n changed", ev)
|
||||
s.Log.Println("i18n changed", ev)
|
||||
i18nChanged = true
|
||||
|
||||
}
|
||||
|
|
|
@ -18,10 +18,12 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
radix "github.com/armon/go-radix"
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
|
@ -100,19 +102,41 @@ func (s *Site) Debug() {
|
|||
func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
|
||||
conf := cfg.Configs.GetFirstLanguageConfig()
|
||||
|
||||
logger := cfg.Logger
|
||||
if logger == nil {
|
||||
logger = loggers.NewErrorLogger()
|
||||
var logger loggers.Logger
|
||||
if cfg.TestLogger != nil {
|
||||
logger = cfg.TestLogger
|
||||
} else {
|
||||
var logHookLast func(e *logg.Entry) error
|
||||
if cfg.Configs.Base.PanicOnWarning {
|
||||
logHookLast = loggers.PanicOnWarningHook
|
||||
}
|
||||
if cfg.LogOut == nil {
|
||||
cfg.LogOut = os.Stdout
|
||||
}
|
||||
if cfg.LogLevel == 0 {
|
||||
cfg.LogLevel = logg.LevelWarn
|
||||
}
|
||||
|
||||
logOpts := loggers.Options{
|
||||
Level: cfg.LogLevel,
|
||||
Distinct: true, // This will drop duplicate log warning and errors.
|
||||
HandlerPost: logHookLast,
|
||||
Stdout: cfg.LogOut,
|
||||
Stderr: cfg.LogOut,
|
||||
StoreErrors: conf.Running(),
|
||||
SuppresssStatements: conf.IgnoredErrors(),
|
||||
}
|
||||
logger = loggers.New(logOpts)
|
||||
}
|
||||
ignorableLogger := loggers.NewIgnorableLogger(logger, conf.IgnoredErrors())
|
||||
|
||||
firstSiteDeps := &deps.Deps{
|
||||
Fs: cfg.Fs,
|
||||
Log: ignorableLogger,
|
||||
Log: logger,
|
||||
Conf: conf,
|
||||
TemplateProvider: tplimpl.DefaultTemplateProvider,
|
||||
TranslationProvider: i18n.NewTranslationProvider(),
|
||||
}
|
||||
|
||||
if err := firstSiteDeps.Init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -128,7 +152,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
|
|||
k := language.Lang
|
||||
conf := confm.LanguageConfigMap[k]
|
||||
|
||||
frontmatterHandler, err := pagemeta.NewFrontmatterHandler(cfg.Logger, conf.Frontmatter)
|
||||
frontmatterHandler, err := pagemeta.NewFrontmatterHandler(firstSiteDeps.Log, conf.Frontmatter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -209,6 +233,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
|
|||
}
|
||||
|
||||
return h, err
|
||||
|
||||
}
|
||||
|
||||
func newHugoSitesNew(cfg deps.DepsCfg, d *deps.Deps, sites []*Site) (*HugoSites, error) {
|
||||
|
|
|
@ -181,7 +181,7 @@ func (s *Site) logMissingLayout(name, layout, kind, outputFormat string) {
|
|||
|
||||
msg += ": " + errMsg
|
||||
|
||||
log.Printf(msg, args...)
|
||||
log.Logf(msg, args...)
|
||||
}
|
||||
|
||||
// renderPaginator must be run after the owning Page has been rendered.
|
||||
|
|
|
@ -33,6 +33,7 @@ import (
|
|||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
|
@ -47,7 +48,6 @@ import (
|
|||
"github.com/gohugoio/hugo/resources/resource"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
)
|
||||
|
||||
|
@ -552,7 +552,7 @@ func (s *sitesBuilder) CreateSitesE() error {
|
|||
if depsCfg.Configs.IsZero() {
|
||||
depsCfg.Configs = s.Configs
|
||||
}
|
||||
depsCfg.Logger = s.logger
|
||||
depsCfg.TestLogger = s.logger
|
||||
|
||||
sites, err := NewHugoSites(depsCfg)
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import (
|
|||
"github.com/gohugoio/hugo/common/hreflect"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
|
||||
"github.com/gohugoio/go-i18n/v2/i18n"
|
||||
|
@ -32,8 +31,6 @@ import (
|
|||
|
||||
type translateFunc func(ctx context.Context, translationID string, templateData any) string
|
||||
|
||||
var i18nWarningLogger = helpers.NewDistinctErrorLogger()
|
||||
|
||||
// Translator handles i18n translations.
|
||||
type Translator struct {
|
||||
translateFuncs map[string]translateFunc
|
||||
|
@ -123,7 +120,7 @@ func (t Translator) initFuncs(bndl *i18n.Bundle) {
|
|||
}
|
||||
|
||||
if t.cfg.LogI18nWarnings() {
|
||||
i18nWarningLogger.Printf("i18n|MISSING_TRANSLATION|%s|%s", currentLangStr, translationID)
|
||||
t.logger.Warnf("i18n|MISSING_TRANSLATION|%s|%s", currentLangStr, translationID)
|
||||
}
|
||||
|
||||
if enableMissingTranslationPlaceholders {
|
||||
|
|
|
@ -19,12 +19,13 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/types"
|
||||
"github.com/gohugoio/hugo/config/testconfig"
|
||||
|
||||
"github.com/gohugoio/hugo/tpl/tplimpl"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
"github.com/spf13/afero"
|
||||
|
||||
|
@ -34,7 +35,7 @@ import (
|
|||
"github.com/gohugoio/hugo/config"
|
||||
)
|
||||
|
||||
var logger = loggers.NewErrorLogger()
|
||||
var logger = loggers.NewDefault()
|
||||
|
||||
type i18nTest struct {
|
||||
name string
|
||||
|
@ -406,7 +407,7 @@ other = "{{ . }} miesiąca"
|
|||
|
||||
for _, variant := range test.variants {
|
||||
c.Assert(f(ctx, test.id, variant.Key), qt.Equals, variant.Value, qt.Commentf("input: %v", variant.Key))
|
||||
c.Assert(int(d.Log.LogCounters().WarnCounter.Count()), qt.Equals, 0)
|
||||
c.Assert(d.Log.LoggCount(logg.LevelWarn), qt.Equals, 0)
|
||||
}
|
||||
|
||||
})
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestAsciidoctorDefaultArgs(t *testing.T) {
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -76,7 +76,7 @@ func TestAsciidoctorNonDefaultArgs(t *testing.T) {
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -106,7 +106,7 @@ func TestAsciidoctorDisallowedArgs(t *testing.T) {
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -130,7 +130,7 @@ func TestAsciidoctorArbitraryExtension(t *testing.T) {
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -164,7 +164,7 @@ func TestAsciidoctorDisallowedExtension(t *testing.T) {
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -195,7 +195,7 @@ trace = false
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -232,7 +232,7 @@ extensions = ["asciidoctor-html5s", "asciidoctor-diagram"]
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -272,7 +272,7 @@ my-attribute-name = "my value"
|
|||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
@ -311,7 +311,7 @@ allow = ['asciidoctor']
|
|||
|
||||
p, err := asciidocext.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
Conf: conf,
|
||||
Exec: hexec.New(securityConfig),
|
||||
},
|
||||
|
|
|
@ -46,7 +46,7 @@ noclasses=false
|
|||
|
||||
func convert(c *qt.C, conf config.AllProvider, content string) converter.ResultRender {
|
||||
pconf := converter.ProviderConfig{
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
Conf: conf,
|
||||
}
|
||||
|
||||
|
@ -442,7 +442,7 @@ LINE5
|
|||
conf := testconfig.GetTestConfig(nil, cfg)
|
||||
pcfg := converter.ProviderConfig{
|
||||
Conf: conf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
}
|
||||
p, err := goldmark.Provider.New(
|
||||
pcfg,
|
||||
|
|
|
@ -17,12 +17,11 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/config/testconfig"
|
||||
"github.com/gohugoio/hugo/markup/converter/hooks"
|
||||
"github.com/gohugoio/hugo/markup/goldmark"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/markup/converter"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
|
@ -56,7 +55,7 @@ And then some.
|
|||
p, err := goldmark.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: testconfig.GetTestConfig(nil, nil),
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
})
|
||||
c.Assert(err, qt.IsNil)
|
||||
conv, err := p.New(converter.DocumentContext{})
|
||||
|
@ -86,12 +85,12 @@ func TestEscapeToc(t *testing.T) {
|
|||
safeP, _ := goldmark.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: safeConf(),
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
})
|
||||
unsafeP, _ := goldmark.Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Conf: unsafeConf(),
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
})
|
||||
safeConv, _ := safeP.New(converter.DocumentContext{})
|
||||
unsafeConv, _ := unsafeP.New(converter.DocumentContext{})
|
||||
|
|
|
@ -16,6 +16,7 @@ package org
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
|
||||
|
@ -46,7 +47,7 @@ type orgConverter struct {
|
|||
func (c *orgConverter) Convert(ctx converter.RenderContext) (converter.ResultRender, error) {
|
||||
logger := c.cfg.Logger
|
||||
config := org.New()
|
||||
config.Log = logger.Warn()
|
||||
config.Log = log.Default() // TODO(bep)
|
||||
config.ReadFile = func(filename string) ([]byte, error) {
|
||||
return afero.ReadFile(c.cfg.ContentFs, filename)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
func TestConvert(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
p, err := org.Provider.New(converter.ProviderConfig{
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
Conf: testconfig.GetTestConfig(afero.NewMemMapFs(), nil),
|
||||
})
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestConvert(t *testing.T) {
|
|||
c := qt.New(t)
|
||||
sc := security.DefaultConfig
|
||||
sc.Exec.Allow = security.NewWhitelist("pandoc")
|
||||
p, err := Provider.New(converter.ProviderConfig{Exec: hexec.New(sc), Logger: loggers.NewErrorLogger()})
|
||||
p, err := Provider.New(converter.ProviderConfig{Exec: hexec.New(sc), Logger: loggers.NewDefault()})
|
||||
c.Assert(err, qt.IsNil)
|
||||
conv, err := p.New(converter.DocumentContext{})
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
|
|
@ -35,7 +35,7 @@ func TestConvert(t *testing.T) {
|
|||
|
||||
p, err := Provider.New(
|
||||
converter.ProviderConfig{
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
Logger: loggers.NewDefault(),
|
||||
Exec: hexec.New(sc),
|
||||
})
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/gohugoio/hugo/common/collections"
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
hglob "github.com/gohugoio/hugo/hugofs/glob"
|
||||
|
||||
|
@ -39,8 +40,6 @@ import (
|
|||
|
||||
"github.com/gohugoio/hugo/hugofs/files"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/config"
|
||||
|
||||
"github.com/rogpeppe/go-internal/module"
|
||||
|
@ -98,7 +97,7 @@ func NewClient(cfg ClientConfig) *Client {
|
|||
|
||||
logger := cfg.Logger
|
||||
if logger == nil {
|
||||
logger = loggers.NewWarningLogger()
|
||||
logger = loggers.NewDefault()
|
||||
}
|
||||
|
||||
var noVendor glob.Glob
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
|
@ -28,7 +29,6 @@ import (
|
|||
toml "github.com/pelletier/go-toml/v2"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cast"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
|
@ -231,7 +231,7 @@ func parseORGDate(s string) string {
|
|||
|
||||
func (d Decoder) unmarshalORG(data []byte, v any) error {
|
||||
config := org.New()
|
||||
config.Log = jww.WARN
|
||||
config.Log = log.Default() // TODO(bep)
|
||||
document := config.Parse(bytes.NewReader(data), "")
|
||||
if document.Error != nil {
|
||||
return document.Error
|
||||
|
@ -242,7 +242,7 @@ func (d Decoder) unmarshalORG(data []byte, v any) error {
|
|||
if strings.HasSuffix(k, "[]") {
|
||||
frontMatter[k[:len(k)-2]] = strings.Fields(v)
|
||||
} else if k == "tags" || k == "categories" || k == "aliases" {
|
||||
jww.WARN.Printf("Please use '#+%s[]:' notation, automatic conversion is deprecated.", k)
|
||||
log.Printf("warn: Please use '#+%s[]:' notation, automatic conversion is deprecated.", k)
|
||||
frontMatter[k] = strings.Fields(v)
|
||||
} else if k == "date" || k == "lastmod" || k == "publishdate" || k == "expirydate" {
|
||||
frontMatter[k] = parseORGDate(v)
|
||||
|
|
|
@ -18,9 +18,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/common/htime"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/paths"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/resources/resource"
|
||||
|
||||
|
@ -270,7 +270,7 @@ func toLowerSlice(in any) []string {
|
|||
// If no logger is provided, one will be created.
|
||||
func NewFrontmatterHandler(logger loggers.Logger, frontMatterConfig FrontmatterConfig) (FrontMatterHandler, error) {
|
||||
if logger == nil {
|
||||
logger = loggers.NewErrorLogger()
|
||||
logger = loggers.NewDefault()
|
||||
}
|
||||
|
||||
allDateKeys := make(map[string]bool)
|
||||
|
|
|
@ -30,7 +30,7 @@ func newTestPathSpecFor(cfg config.Provider) *helpers.PathSpec {
|
|||
mfs := afero.NewMemMapFs()
|
||||
conf := testconfig.GetTestConfig(mfs, cfg)
|
||||
fs := hugofs.NewFrom(mfs, conf.BaseConfig())
|
||||
ps, err := helpers.NewPathSpec(fs, conf, loggers.NewErrorLogger())
|
||||
ps, err := helpers.NewPathSpec(fs, conf, loggers.NewDefault())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
|
||||
|
@ -39,7 +40,6 @@ import (
|
|||
"github.com/gohugoio/hugo/resources/postpub"
|
||||
|
||||
"github.com/gohugoio/hugo/cache/filecache"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
"github.com/gohugoio/hugo/resources/images"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
|
@ -75,7 +75,7 @@ func NewSpec(
|
|||
}
|
||||
|
||||
if logger == nil {
|
||||
logger = loggers.NewErrorLogger()
|
||||
logger = loggers.NewDefault()
|
||||
}
|
||||
|
||||
permalinks, err := page.NewPermalinkExpander(s.URLize, conf.Permalinks)
|
||||
|
|
|
@ -122,10 +122,10 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
|
|||
}
|
||||
|
||||
var configFile string
|
||||
logger := t.rs.Logger
|
||||
infol := t.rs.Logger.InfoCommand(binaryName)
|
||||
infoW := loggers.LevelLoggerToWriter(infol)
|
||||
|
||||
var errBuf bytes.Buffer
|
||||
infoW := loggers.LoggerToWriterWithPrefix(logger.Info(), "babel")
|
||||
|
||||
if t.options.Config != "" {
|
||||
configFile = t.options.Config
|
||||
|
@ -149,7 +149,7 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
|
|||
var cmdArgs []any
|
||||
|
||||
if configFile != "" {
|
||||
logger.Infoln("babel: use config file", configFile)
|
||||
infol.Logf("use config file %q", configFile)
|
||||
cmdArgs = []any{"--config-file", configFile}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@ package babel_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/htesting"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
)
|
||||
|
@ -82,7 +81,7 @@ Transpiled3: {{ $transpiled.Permalink }}
|
|||
TxtarString: files,
|
||||
NeedsOsFS: true,
|
||||
NeedsNpmInstall: true,
|
||||
LogLevel: jww.LevelInfo,
|
||||
LogLevel: logg.LevelInfo,
|
||||
}).Build()
|
||||
|
||||
b.AssertLogContains("babel: Hugo Environment: production")
|
||||
|
|
|
@ -16,11 +16,11 @@ package postcss_test
|
|||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
|
||||
"github.com/bep/logg"
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/htesting"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
@ -124,7 +124,7 @@ func TestTransformPostCSS(t *testing.T) {
|
|||
T: c,
|
||||
NeedsOsFS: true,
|
||||
NeedsNpmInstall: true,
|
||||
LogLevel: jww.LevelInfo,
|
||||
LogLevel: logg.LevelInfo,
|
||||
WorkingDir: tempDir,
|
||||
TxtarString: files,
|
||||
}).Build()
|
||||
|
@ -148,6 +148,11 @@ func TestTransformPostCSSError(t *testing.T) {
|
|||
t.Skip("Skip long running test when running locally")
|
||||
}
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
//TODO(bep) This has started to fail on Windows with Go 1.19 on GitHub Actions for some mysterious reason.
|
||||
t.Skip("Skip on Windows")
|
||||
}
|
||||
|
||||
c := qt.New(t)
|
||||
|
||||
s, err := hugolib.NewIntegrationTestBuilder(
|
||||
|
@ -176,7 +181,7 @@ func TestTransformPostCSSImportError(t *testing.T) {
|
|||
T: c,
|
||||
NeedsOsFS: true,
|
||||
NeedsNpmInstall: true,
|
||||
LogLevel: jww.LevelInfo,
|
||||
LogLevel: logg.LevelInfo,
|
||||
TxtarString: strings.ReplaceAll(postCSSIntegrationTestFiles, `@import "components/all.css";`, `@import "components/doesnotexist.css";`),
|
||||
}).BuildE()
|
||||
|
||||
|
@ -201,7 +206,7 @@ func TestTransformPostCSSImporSkipInlineImportsNotFound(t *testing.T) {
|
|||
T: c,
|
||||
NeedsOsFS: true,
|
||||
NeedsNpmInstall: true,
|
||||
LogLevel: jww.LevelInfo,
|
||||
LogLevel: logg.LevelInfo,
|
||||
TxtarString: files,
|
||||
}).Build()
|
||||
|
||||
|
@ -233,7 +238,7 @@ func TestTransformPostCSSResourceCacheWithPathInBaseURL(t *testing.T) {
|
|||
T: c,
|
||||
NeedsOsFS: true,
|
||||
NeedsNpmInstall: true,
|
||||
LogLevel: jww.LevelInfo,
|
||||
LogLevel: logg.LevelInfo,
|
||||
TxtarString: files,
|
||||
WorkingDir: tempDir,
|
||||
}).Build()
|
||||
|
|
|
@ -27,13 +27,12 @@ import (
|
|||
|
||||
"github.com/gohugoio/hugo/common/collections"
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/text"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/resources/internal"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cast"
|
||||
|
@ -151,10 +150,12 @@ func (t *postcssTransformation) Key() internal.ResourceTransformationKey {
|
|||
func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
|
||||
const binaryName = "postcss"
|
||||
|
||||
infol := t.rs.Logger.InfoCommand(binaryName)
|
||||
infoW := loggers.LevelLoggerToWriter(infol)
|
||||
|
||||
ex := t.rs.ExecHelper
|
||||
|
||||
var configFile string
|
||||
logger := t.rs.Logger
|
||||
|
||||
var options Options
|
||||
if t.optionsm != nil {
|
||||
|
@ -185,7 +186,7 @@ func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationC
|
|||
var cmdArgs []any
|
||||
|
||||
if configFile != "" {
|
||||
logger.Infoln("postcss: use config file", configFile)
|
||||
infol.Logf("use config file %q", configFile)
|
||||
cmdArgs = []any{"--config", configFile}
|
||||
}
|
||||
|
||||
|
@ -194,7 +195,6 @@ func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationC
|
|||
}
|
||||
|
||||
var errBuf bytes.Buffer
|
||||
infoW := loggers.LoggerToWriterWithPrefix(logger.Info(), "postcss")
|
||||
|
||||
stderr := io.MultiWriter(infoW, &errBuf)
|
||||
cmdArgs = append(cmdArgs, hexec.WithStderr(stderr))
|
||||
|
@ -401,7 +401,6 @@ func (imp *importResolver) shouldImport(s string) bool {
|
|||
}
|
||||
|
||||
func (imp *importResolver) toFileError(output string) error {
|
||||
output = strings.TrimSpace(loggers.RemoveANSIColours(output))
|
||||
inErr := errors.New(output)
|
||||
|
||||
match := cssSyntaxErrorRe.FindStringSubmatch(output)
|
||||
|
|
|
@ -18,9 +18,9 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/htesting/hqt"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
|
@ -95,7 +95,7 @@ LOCAL_STYLE
|
|||
mainStyles,
|
||||
"styles.css",
|
||||
Options{},
|
||||
fs, loggers.NewErrorLogger(),
|
||||
fs, loggers.NewDefault(),
|
||||
)
|
||||
|
||||
r, err := imp.resolve()
|
||||
|
@ -144,7 +144,7 @@ LOCAL_STYLE
|
|||
@import "e.css";
|
||||
@import "missing.css";`
|
||||
|
||||
logger := loggers.NewErrorLogger()
|
||||
logger := loggers.NewDefault()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
|
|
|
@ -58,6 +58,8 @@ func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error)
|
|||
transpiler *godartsass.Transpiler
|
||||
transpilerv1 *godartsassv1.Transpiler
|
||||
err error
|
||||
infol = rs.Logger.InfoCommand("Dart Sass")
|
||||
warnl = rs.Logger.WarnCommand("Dart Sass")
|
||||
)
|
||||
|
||||
if hugo.IsDartSassV2() {
|
||||
|
@ -68,10 +70,10 @@ func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error)
|
|||
switch event.Type {
|
||||
case godartsass.LogEventTypeDebug:
|
||||
// Log as Info for now, we may adjust this if it gets too chatty.
|
||||
rs.Logger.Infof("Dart Sass: %s", message)
|
||||
infol.Logf(message)
|
||||
default:
|
||||
// The rest are either deprecations or @warn statements.
|
||||
rs.Logger.Warnf("Dart Sass: %s", message)
|
||||
warnl.Logf(message)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
@ -84,10 +86,10 @@ func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error)
|
|||
switch event.Type {
|
||||
case godartsassv1.LogEventTypeDebug:
|
||||
// Log as Info for now, we may adjust this if it gets too chatty.
|
||||
rs.Logger.Infof("Dart Sass: %s", message)
|
||||
infol.Logf(message)
|
||||
default:
|
||||
// The rest are either deprecations or @warn statements.
|
||||
rs.Logger.Warnf("Dart Sass: %s", message)
|
||||
warnl.Logf(message)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
|
@ -17,10 +17,10 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
"github.com/gohugoio/hugo/resources/resource_transformers/tocss/dartsass"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
func TestTransformIncludePaths(t *testing.T) {
|
||||
|
@ -288,11 +288,11 @@ T1: {{ $r.Content }}
|
|||
T: t,
|
||||
TxtarString: files,
|
||||
NeedsOsFS: true,
|
||||
LogLevel: jww.LevelInfo,
|
||||
LogLevel: logg.LevelInfo,
|
||||
}).Build()
|
||||
|
||||
b.AssertLogMatches(`WARN.*Dart Sass: foo`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:1:0: bar`)
|
||||
b.AssertLogMatches(`Dart Sass: foo`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:1:0: bar`)
|
||||
|
||||
}
|
||||
|
||||
|
@ -513,20 +513,20 @@ T1: {{ $r.Content }}
|
|||
T: t,
|
||||
TxtarString: files,
|
||||
NeedsOsFS: true,
|
||||
LogLevel: jww.LevelInfo,
|
||||
LogLevel: logg.LevelInfo,
|
||||
}).Build()
|
||||
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:3:0: color`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:4:0: color`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:5:0: color`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:6:0: number`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:7:0: number`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:8:0: number`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:9:0: string`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:10:0: string`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:11:0: string`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:12:0: number`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:13:0: number`)
|
||||
b.AssertLogMatches(`INFO.*Dart Sass: .*assets.*main.scss:14:0: number`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:3:0: color`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:4:0: color`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:5:0: color`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:6:0: number`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:7:0: number`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:8:0: number`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:9:0: string`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:10:0: string`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:11:0: string`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:12:0: number`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:13:0: number`)
|
||||
b.AssertLogMatches(`Dart Sass: .*assets.*main.scss:14:0: number`)
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import (
|
|||
"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"
|
||||
|
@ -393,7 +392,7 @@ func (ns *Namespace) IsSet(c any, key any) (bool, error) {
|
|||
return av.MapIndex(kv).IsValid(), nil
|
||||
}
|
||||
default:
|
||||
helpers.DistinctErrorLog.Printf("WARNING: calling IsSet with unsupported type %q (%T) will always return false.\n", av.Kind(), c)
|
||||
ns.deps.Log.Warnf("calling IsSet with unsupported type %q (%T) will always return false.\n", av.Kind(), c)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
|
|
|
@ -30,7 +30,6 @@ import (
|
|||
"github.com/gohugoio/hugo/common/types"
|
||||
|
||||
"github.com/gohugoio/hugo/common/constants"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
|
||||
|
@ -92,7 +91,7 @@ func (ns *Namespace) GetCSV(sep string, args ...any) (d [][]string, err error) {
|
|||
if security.IsAccessDenied(err) {
|
||||
return nil, err
|
||||
}
|
||||
ns.deps.Log.(loggers.IgnorableLogger).Errorsf(constants.ErrRemoteGetCSV, "Failed to get CSV resource %q: %s", url, err)
|
||||
ns.deps.Log.Errorsf(constants.ErrRemoteGetCSV, "Failed to get CSV resource %q: %s", url, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -128,7 +127,7 @@ func (ns *Namespace) GetJSON(args ...any) (any, error) {
|
|||
if security.IsAccessDenied(err) {
|
||||
return nil, err
|
||||
}
|
||||
ns.deps.Log.(loggers.IgnorableLogger).Errorsf(constants.ErrRemoteGetJSON, "Failed to get JSON resource %q: %s", url, err)
|
||||
ns.deps.Log.Errorsf(constants.ErrRemoteGetJSON, "Failed to get JSON resource %q: %s", url, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
|
@ -108,13 +109,13 @@ func TestGetCSV(t *testing.T) {
|
|||
got, err := ns.GetCSV(test.sep, test.url)
|
||||
|
||||
if _, ok := test.expect.(bool); ok {
|
||||
c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 1)
|
||||
c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 1)
|
||||
c.Assert(got, qt.IsNil)
|
||||
return
|
||||
}
|
||||
|
||||
c.Assert(err, qt.IsNil, msg)
|
||||
c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0)
|
||||
c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 0)
|
||||
c.Assert(got, qt.Not(qt.IsNil), msg)
|
||||
c.Assert(got, qt.DeepEquals, test.expect, msg)
|
||||
})
|
||||
|
@ -200,11 +201,11 @@ func TestGetJSON(t *testing.T) {
|
|||
got, _ := ns.GetJSON(test.url)
|
||||
|
||||
if _, ok := test.expect.(bool); ok {
|
||||
c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 1)
|
||||
c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 1)
|
||||
return
|
||||
}
|
||||
|
||||
c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0, msg)
|
||||
c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 0, msg)
|
||||
c.Assert(got, qt.Not(qt.IsNil), msg)
|
||||
c.Assert(got, qt.DeepEquals, test.expect)
|
||||
|
||||
|
@ -283,7 +284,7 @@ func TestHeaders(t *testing.T) {
|
|||
err := fn("http://example.org/api", "?foo", test.headers)
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(int(ns.deps.Log.LogCounters().ErrorCounter.Count()), qt.Equals, 0)
|
||||
c.Assert(int(ns.deps.Log.LoggCount(logg.LevelError)), qt.Equals, 0)
|
||||
test.assert(c, headers.String())
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ package data
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
|
@ -29,7 +32,6 @@ import (
|
|||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/gohugoio/hugo/cache/filecache"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
@ -182,7 +184,7 @@ func TestScpGetRemoteParallel(t *testing.T) {
|
|||
|
||||
func newDeps(cfg config.Provider) *deps.Deps {
|
||||
conf := testconfig.GetTestConfig(nil, cfg)
|
||||
logger := loggers.NewIgnorableLogger(loggers.NewErrorLogger(), nil)
|
||||
logger := loggers.NewDefault()
|
||||
fs := hugofs.NewFrom(afero.NewMemMapFs(), conf.BaseConfig())
|
||||
|
||||
d := &deps.Deps{
|
||||
|
|
|
@ -16,27 +16,22 @@ package fmt
|
|||
|
||||
import (
|
||||
_fmt "fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
// New returns a new instance of the fmt-namespaced template functions.
|
||||
func New(d *deps.Deps) *Namespace {
|
||||
ignorableLogger, ok := d.Log.(loggers.IgnorableLogger)
|
||||
if !ok {
|
||||
ignorableLogger = loggers.NewIgnorableLogger(d.Log, nil)
|
||||
}
|
||||
|
||||
distinctLogger := helpers.NewDistinctLogger(d.Log)
|
||||
ns := &Namespace{
|
||||
distinctLogger: ignorableLogger.Apply(distinctLogger),
|
||||
logger: d.Log,
|
||||
}
|
||||
|
||||
d.BuildStartListeners.Add(func() {
|
||||
ns.distinctLogger.Reset()
|
||||
ns.logger.Reset()
|
||||
})
|
||||
|
||||
return ns
|
||||
|
@ -44,7 +39,7 @@ func New(d *deps.Deps) *Namespace {
|
|||
|
||||
// Namespace provides template functions for the "fmt" namespace.
|
||||
type Namespace struct {
|
||||
distinctLogger loggers.IgnorableLogger
|
||||
logger loggers.Logger
|
||||
}
|
||||
|
||||
// Print returns a string representation of args.
|
||||
|
@ -65,7 +60,7 @@ func (ns *Namespace) Println(args ...any) string {
|
|||
// Errorf formats args according to a format specifier and logs an ERROR.
|
||||
// It returns an empty string.
|
||||
func (ns *Namespace) Errorf(format string, args ...any) string {
|
||||
ns.distinctLogger.Errorf(format, args...)
|
||||
ns.logger.Errorf(format, args...)
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -73,13 +68,41 @@ func (ns *Namespace) Errorf(format string, args ...any) string {
|
|||
// an information text that the error with the given id can be suppressed in config.
|
||||
// It returns an empty string.
|
||||
func (ns *Namespace) Erroridf(id, format string, args ...any) string {
|
||||
ns.distinctLogger.Errorsf(id, format, args...)
|
||||
ns.logger.Errorsf(id, format, args...)
|
||||
return ""
|
||||
}
|
||||
|
||||
// Warnf formats args according to a format specifier and logs a WARNING.
|
||||
// It returns an empty string.
|
||||
func (ns *Namespace) Warnf(format string, args ...any) string {
|
||||
ns.distinctLogger.Warnf(format, args...)
|
||||
ns.logger.Warnf(format, args...)
|
||||
return ""
|
||||
}
|
||||
|
||||
// Warnmf is epxermimental and subject to change at any time.
|
||||
func (ns *Namespace) Warnmf(m any, format string, args ...any) string {
|
||||
return ns.logmf(ns.logger.Warn(), m, format, args...)
|
||||
}
|
||||
|
||||
// Errormf is epxermimental and subject to change at any time.
|
||||
func (ns *Namespace) Errormf(m any, format string, args ...any) string {
|
||||
return ns.logmf(ns.logger.Error(), m, format, args...)
|
||||
}
|
||||
|
||||
func (ns *Namespace) logmf(l logg.LevelLogger, m any, format string, args ...any) string {
|
||||
mm := cast.ToStringMap(m)
|
||||
fields := make(logg.Fields, len(mm))
|
||||
i := 0
|
||||
for k, v := range mm {
|
||||
fields[i] = logg.Field{Name: k, Value: v}
|
||||
i++
|
||||
}
|
||||
// Sort the fields to make the output deterministic.
|
||||
sort.Slice(fields, func(i, j int) bool {
|
||||
return fields[i].Name < fields[j].Name
|
||||
})
|
||||
|
||||
l.WithFields(fields).Logf(format, args...)
|
||||
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
|
||||
"github.com/gohugoio/hugo/transform"
|
||||
)
|
||||
|
||||
|
@ -90,7 +91,7 @@ func New(baseURL url.URL) transform.Transformer {
|
|||
c = append(c[:i], append(script, c[i:]...)...)
|
||||
|
||||
if _, err := ft.To().Write(c); err != nil {
|
||||
helpers.DistinctWarnLog.Println("Failed to inject LiveReload script:", err)
|
||||
loggers.Log().Warnf("Failed to inject LiveReload script:", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"regexp"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/transform"
|
||||
)
|
||||
|
||||
|
@ -33,7 +33,7 @@ func HugoGenerator(ft transform.FromTo) error {
|
|||
b := ft.From().Bytes()
|
||||
if metaTagsCheck.Match(b) {
|
||||
if _, err := ft.To().Write(b); err != nil {
|
||||
helpers.DistinctWarnLog.Println("Failed to inject Hugo generator tag:", err)
|
||||
loggers.Log().Warnf("Failed to inject Hugo generator tag: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func HugoGenerator(ft transform.FromTo) error {
|
|||
}
|
||||
|
||||
if _, err := ft.To().Write(newcontent); err != nil {
|
||||
helpers.DistinctWarnLog.Println("Failed to inject Hugo generator tag:", err)
|
||||
loggers.Log().Warnf("Failed to inject Hugo generator tag: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
Loading…
Reference in a new issue