Improve error messages, esp. when the server is running

* Add file context to minifier errors when publishing
* Misc fixes (see issues)
* Allow custom server error template in layouts/server/error.html

To get to this, this commit also cleans up and simplifies the code surrounding errors and files. This also removes the usage of `github.com/pkg/errors`, mostly because of https://github.com/pkg/errors/issues/223 -- but also because most of this is now built-in to Go.

Fixes #9852
Fixes #9857
Fixes #9863
This commit is contained in:
Bjørn Erik Pedersen 2022-05-02 16:07:52 +02:00
parent 6eea32bd6b
commit f2946da9e8
109 changed files with 861 additions and 780 deletions

View file

@ -14,6 +14,7 @@
package filecache package filecache
import ( import (
"fmt"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
@ -25,8 +26,9 @@ import (
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"errors"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -153,7 +155,7 @@ func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
} }
if err := decoder.Decode(v); err != nil { if err := decoder.Decode(v); err != nil {
return nil, errors.Wrap(err, "failed to decode filecache config") return nil, fmt.Errorf("failed to decode filecache config: %w", err)
} }
if cc.Dir == "" { if cc.Dir == "" {
@ -162,7 +164,7 @@ func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
name := strings.ToLower(k) name := strings.ToLower(k)
if !valid[name] { if !valid[name] {
return nil, errors.Errorf("%q is not a valid cache name", name) return nil, fmt.Errorf("%q is not a valid cache name", name)
} }
c[name] = cc c[name] = cc
@ -197,12 +199,12 @@ func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
if !v.isResourceDir { if !v.isResourceDir {
if isOsFs && !filepath.IsAbs(v.Dir) { if isOsFs && !filepath.IsAbs(v.Dir) {
return c, errors.Errorf("%q must resolve to an absolute directory", v.Dir) return c, fmt.Errorf("%q must resolve to an absolute directory", v.Dir)
} }
// Avoid cache in root, e.g. / (Unix) or c:\ (Windows) // Avoid cache in root, e.g. / (Unix) or c:\ (Windows)
if len(strings.TrimPrefix(v.Dir, filepath.VolumeName(v.Dir))) == 1 { if len(strings.TrimPrefix(v.Dir, filepath.VolumeName(v.Dir))) == 1 {
return c, errors.Errorf("%q is a root folder and not allowed as cache dir", v.Dir) return c, fmt.Errorf("%q is a root folder and not allowed as cache dir", v.Dir)
} }
} }
@ -242,5 +244,5 @@ func resolveDirPlaceholder(fs afero.Fs, cfg config.Provider, placeholder string)
return filepath.Base(workingDir), false, nil return filepath.Base(workingDir), false, nil
} }
return "", false, errors.Errorf("%q is not a valid placeholder (valid values are :cacheDir or :resourceDir)", placeholder) return "", false, fmt.Errorf("%q is not a valid placeholder (valid values are :cacheDir or :resourceDir)", placeholder)
} }

View file

@ -14,12 +14,12 @@
package filecache package filecache
import ( import (
"fmt"
"io" "io"
"os" "os"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -39,7 +39,7 @@ func (c Caches) Prune() (int, error) {
if os.IsNotExist(err) { if os.IsNotExist(err) {
continue continue
} }
return counter, errors.Wrapf(err, "failed to prune cache %q", k) return counter, fmt.Errorf("failed to prune cache %q: %w", k, err)
} }
} }

View file

@ -14,7 +14,6 @@
package commands package commands
import ( import (
"bytes"
"errors" "errors"
"io/ioutil" "io/ioutil"
"net" "net"
@ -141,19 +140,11 @@ func (c *commandeer) getErrorWithContext() any {
m := make(map[string]any) m := make(map[string]any)
m["Error"] = errors.New(removeErrorPrefixFromLog(c.logger.Errors())) //xwm["Error"] = errors.New(cleanErrorLog(removeErrorPrefixFromLog(c.logger.Errors())))
m["Error"] = errors.New(cleanErrorLog(removeErrorPrefixFromLog(c.logger.Errors())))
m["Version"] = hugo.BuildVersionString() m["Version"] = hugo.BuildVersionString()
ferrors := herrors.UnwrapFileErrorsWithErrorContext(c.buildErr)
fe := herrors.UnwrapErrorWithFileContext(c.buildErr) m["Files"] = ferrors
if fe != nil {
m["File"] = fe
}
if c.h.verbose {
var b bytes.Buffer
herrors.FprintStackTraceFromErr(&b, c.buildErr)
m["StackTrace"] = b.String()
}
return m return m
} }

View file

@ -31,8 +31,6 @@ import (
"github.com/gohugoio/hugo/parser" "github.com/gohugoio/hugo/parser"
"github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/parser/metadecoders"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/hugolib" "github.com/gohugoio/hugo/hugolib"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -193,7 +191,7 @@ func (cc *convertCmd) convertAndSavePage(p page.Page, site *hugolib.Site, target
fs := hugofs.Os fs := hugofs.Os
if err := helpers.WriteToDisk(newFilename, &newContent, fs); err != nil { if err := helpers.WriteToDisk(newFilename, &newContent, fs); err != nil {
return errors.Wrapf(err, "Failed to save file %q:", newFilename) return fmt.Errorf("Failed to save file %q:: %w", newFilename, err)
} }
return nil return nil

View file

@ -39,9 +39,6 @@ import (
"github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/page"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/terminal" "github.com/gohugoio/hugo/common/terminal"
@ -300,14 +297,14 @@ func (c *commandeer) fullBuild(noBuildLock bool) error {
copyStaticFunc := func() error { copyStaticFunc := func() error {
cnt, err := c.copyStatic() cnt, err := c.copyStatic()
if err != nil { if err != nil {
return errors.Wrap(err, "Error copying static files") return fmt.Errorf("Error copying static files: %w", err)
} }
langCount = cnt langCount = cnt
return nil return nil
} }
buildSitesFunc := func() error { buildSitesFunc := func() error {
if err := c.buildSites(noBuildLock); err != nil { if err := c.buildSites(noBuildLock); err != nil {
return errors.Wrap(err, "Error building site") return fmt.Errorf("Error building site: %w", err)
} }
return nil return nil
} }
@ -354,10 +351,10 @@ func (c *commandeer) initCPUProfile() (func(), error) {
f, err := os.Create(c.h.cpuprofile) f, err := os.Create(c.h.cpuprofile)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to create CPU profile") return nil, fmt.Errorf("failed to create CPU profile: %w", err)
} }
if err := pprof.StartCPUProfile(f); err != nil { if err := pprof.StartCPUProfile(f); err != nil {
return nil, errors.Wrap(err, "failed to start CPU profile") return nil, fmt.Errorf("failed to start CPU profile: %w", err)
} }
return func() { return func() {
pprof.StopCPUProfile() pprof.StopCPUProfile()
@ -388,11 +385,11 @@ func (c *commandeer) initTraceProfile() (func(), error) {
f, err := os.Create(c.h.traceprofile) f, err := os.Create(c.h.traceprofile)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to create trace file") return nil, fmt.Errorf("failed to create trace file: %w", err)
} }
if err := trace.Start(f); err != nil { if err := trace.Start(f); err != nil {
return nil, errors.Wrap(err, "failed to start trace") return nil, fmt.Errorf("failed to start trace: %w", err)
} }
return func() { return func() {
@ -735,9 +732,7 @@ func (c *commandeer) handleBuildErr(err error, msg string) {
c.logger.Errorln(msg + ":\n") c.logger.Errorln(msg + ":\n")
c.logger.Errorln(helpers.FirstUpper(err.Error())) c.logger.Errorln(helpers.FirstUpper(err.Error()))
if !c.h.quiet && c.h.verbose {
herrors.PrintStackTraceFromErr(err)
}
} }
func (c *commandeer) rebuildSites(events []fsnotify.Event) error { func (c *commandeer) rebuildSites(events []fsnotify.Event) error {

View file

@ -16,14 +16,13 @@ package commands
import ( import (
"bytes" "bytes"
"errors" "errors"
"fmt"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/parser/metadecoders"
_errors "github.com/pkg/errors"
"github.com/gohugoio/hugo/create" "github.com/gohugoio/hugo/create"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
@ -94,7 +93,7 @@ func (n *newSiteCmd) doNewSite(fs *hugofs.Fs, basepath string, force bool) error
for _, dir := range dirs { for _, dir := range dirs {
if err := fs.Source.MkdirAll(dir, 0777); err != nil { if err := fs.Source.MkdirAll(dir, 0777); err != nil {
return _errors.Wrap(err, "Failed to create dir") return fmt.Errorf("Failed to create dir: %w", err)
} }
} }

View file

@ -36,8 +36,6 @@ import (
"github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/paths"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/livereload" "github.com/gohugoio/hugo/livereload"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
@ -366,7 +364,7 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, net.Listener, string
// We're only interested in the path // We're only interested in the path
u, err := url.Parse(baseURL) u, err := url.Parse(baseURL)
if err != nil { if err != nil {
return nil, nil, "", "", errors.Wrap(err, "Invalid baseURL") return nil, nil, "", "", fmt.Errorf("Invalid baseURL: %w", err)
} }
decorate := func(h http.Handler) http.Handler { decorate := func(h http.Handler) http.Handler {
@ -480,6 +478,21 @@ var logErrorRe = regexp.MustCompile(`(?s)ERROR \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{
func removeErrorPrefixFromLog(content string) string { func removeErrorPrefixFromLog(content string) string {
return logErrorRe.ReplaceAllLiteralString(content, "") return logErrorRe.ReplaceAllLiteralString(content, "")
} }
func cleanErrorLog(content string) string {
content = strings.ReplaceAll(content, "Rebuild failed:\n", "")
content = strings.ReplaceAll(content, "\n", "")
seen := make(map[string]bool)
parts := strings.Split(content, ": ")
keep := make([]string, 0, len(parts))
for _, part := range parts {
if seen[part] {
continue
}
seen[part] = true
keep = append(keep, part)
}
return strings.Join(keep, ": ")
}
func (c *commandeer) serve(s *serverCmd) error { func (c *commandeer) serve(s *serverCmd) error {
isMultiHost := c.hugo().IsMultihost() isMultiHost := c.hugo().IsMultihost()
@ -500,17 +513,16 @@ func (c *commandeer) serve(s *serverCmd) error {
roots = []string{""} roots = []string{""}
} }
templ, err := c.hugo().TextTmpl().Parse("__default_server_error", buildErrorTemplate)
if err != nil {
return err
}
srv := &fileServer{ srv := &fileServer{
baseURLs: baseURLs, baseURLs: baseURLs,
roots: roots, roots: roots,
c: c, c: c,
s: s, s: s,
errorTemplate: func(ctx any) (io.Reader, error) { errorTemplate: func(ctx any) (io.Reader, error) {
templ, found := c.hugo().Tmpl().Lookup("server/error.html")
if !found {
panic("template server/error.html not found")
}
b := &bytes.Buffer{} b := &bytes.Buffer{}
err := c.hugo().Tmpl().Execute(templ, b, ctx) err := c.hugo().Tmpl().Execute(templ, b, ctx)
return b, err return b, err
@ -627,7 +639,7 @@ func (sc *serverCmd) fixURL(cfg config.Provider, s string, port int) (string, er
if strings.Contains(u.Host, ":") { if strings.Contains(u.Host, ":") {
u.Host, _, err = net.SplitHostPort(u.Host) u.Host, _, err = net.SplitHostPort(u.Host)
if err != nil { if err != nil {
return "", errors.Wrap(err, "Failed to split baseURL hostpost") return "", fmt.Errorf("Failed to split baseURL hostpost: %w", err)
} }
} }
u.Host += fmt.Sprintf(":%d", port) u.Host += fmt.Sprintf(":%d", port)

View file

@ -22,67 +22,6 @@ import (
"github.com/gohugoio/hugo/transform/livereloadinject" "github.com/gohugoio/hugo/transform/livereloadinject"
) )
var buildErrorTemplate = `<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<title>Hugo Server: Error</title>
<style type="text/css">
body {
font-family: "Muli",avenir, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 16px;
background-color: #2f1e2e;
}
main {
margin: auto;
width: 95%;
padding: 1rem;
}
.version {
color: #ccc;
padding: 1rem 0;
}
.stack {
margin-top: 4rem;
}
pre {
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
.highlight {
overflow-x: auto;
margin-bottom: 1rem;
}
a {
color: #0594cb;
text-decoration: none;
}
a:hover {
color: #ccc;
}
</style>
</head>
<body>
<main>
{{ highlight .Error "apl" "linenos=false,noclasses=true,style=paraiso-dark" }}
{{ with .File }}
{{ $params := printf "noclasses=true,style=paraiso-dark,linenos=table,hl_lines=%d,linenostart=%d" (add .LinesPos 1) (sub .Position.LineNumber .LinesPos) }}
{{ $lexer := .ChromaLexer | default "go-html-template" }}
{{ highlight (delimit .Lines "\n") $lexer $params }}
{{ end }}
{{ with .StackTrace }}
{{ highlight . "apl" "noclasses=true,style=paraiso-dark" }}
{{ end }}
<p class="version">{{ .Version }}</p>
<a href="">Reload Page</a>
</main>
</body>
</html>
`
func injectLiveReloadScript(src io.Reader, baseURL url.URL) string { func injectLiveReloadScript(src io.Reader, baseURL url.URL) string {
var b bytes.Buffer var b bytes.Buffer
chain := transform.Chain{livereloadinject.New(baseURL)} chain := transform.Chain{livereloadinject.New(baseURL)}

View file

@ -1,4 +1,4 @@
// Copyright 2018 The Hugo Authors. All rights reserved. // Copyright 2022 The Hugo Authors. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "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 not use this file except in compliance with the License.
@ -21,8 +21,6 @@ import (
"strings" "strings"
"github.com/gohugoio/hugo/common/text" "github.com/gohugoio/hugo/common/text"
"github.com/spf13/afero"
) )
// LineMatcher contains the elements used to match an error to a line // LineMatcher contains the elements used to match an error to a line
@ -43,8 +41,6 @@ var SimpleLineMatcher = func(m LineMatcher) bool {
return m.Position.LineNumber == m.LineNumber return m.Position.LineNumber == m.LineNumber
} }
var _ text.Positioner = ErrorContext{}
// ErrorContext contains contextual information about an error. This will // ErrorContext contains contextual information about an error. This will
// typically be the lines surrounding some problem in a file. // typically be the lines surrounding some problem in a file.
type ErrorContext struct { type ErrorContext struct {
@ -56,125 +52,11 @@ type ErrorContext struct {
// The position of the error in the Lines above. 0 based. // The position of the error in the Lines above. 0 based.
LinesPos int LinesPos int
position text.Position
// The lexer to use for syntax highlighting. // The lexer to use for syntax highlighting.
// https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages // https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages
ChromaLexer string ChromaLexer string
} }
// Position returns the text position of this error.
func (e ErrorContext) Position() text.Position {
return e.position
}
var _ causer = (*ErrorWithFileContext)(nil)
// ErrorWithFileContext is an error with some additional file context related
// to that error.
type ErrorWithFileContext struct {
cause error
ErrorContext
}
func (e *ErrorWithFileContext) Error() string {
pos := e.Position()
if pos.IsValid() {
return pos.String() + ": " + e.cause.Error()
}
return e.cause.Error()
}
func (e *ErrorWithFileContext) Cause() error {
return e.cause
}
// WithFileContextForFile will try to add a file context with lines matching the given matcher.
// If no match could be found, the original error is returned with false as the second return value.
func WithFileContextForFile(e error, realFilename, filename string, fs afero.Fs, matcher LineMatcherFn) (error, bool) {
f, err := fs.Open(filename)
if err != nil {
return e, false
}
defer f.Close()
return WithFileContext(e, realFilename, f, matcher)
}
// WithFileContextForFileDefault tries to add file context using the default line matcher.
func WithFileContextForFileDefault(err error, filename string, fs afero.Fs) error {
err, _ = WithFileContextForFile(
err,
filename,
filename,
fs,
SimpleLineMatcher)
return err
}
// WithFileContextForFile will try to add a file context with lines matching the given matcher.
// If no match could be found, the original error is returned with false as the second return value.
func WithFileContext(e error, realFilename string, r io.Reader, matcher LineMatcherFn) (error, bool) {
if e == nil {
panic("error missing")
}
le := UnwrapFileError(e)
if le == nil {
var ok bool
if le, ok = ToFileError("", e).(FileError); !ok {
return e, false
}
}
var errCtx ErrorContext
posle := le.Position()
if posle.Offset != -1 {
errCtx = locateError(r, le, func(m LineMatcher) bool {
if posle.Offset >= m.Offset && posle.Offset < m.Offset+len(m.Line) {
lno := posle.LineNumber - m.Position.LineNumber + m.LineNumber
m.Position = text.Position{LineNumber: lno}
}
return matcher(m)
})
} else {
errCtx = locateError(r, le, matcher)
}
pos := &errCtx.position
if pos.LineNumber == -1 {
return e, false
}
pos.Filename = realFilename
if le.Type() != "" {
errCtx.ChromaLexer = chromaLexerFromType(le.Type())
} else {
errCtx.ChromaLexer = chromaLexerFromFilename(realFilename)
}
return &ErrorWithFileContext{cause: e, ErrorContext: errCtx}, true
}
// UnwrapErrorWithFileContext tries to unwrap an ErrorWithFileContext from err.
// It returns nil if this is not possible.
func UnwrapErrorWithFileContext(err error) *ErrorWithFileContext {
for err != nil {
switch v := err.(type) {
case *ErrorWithFileContext:
return v
case causer:
err = v.Cause()
default:
return nil
}
}
return nil
}
func chromaLexerFromType(fileType string) string { func chromaLexerFromType(fileType string) string {
switch fileType { switch fileType {
case "html", "htm": case "html", "htm":
@ -196,23 +78,23 @@ func chromaLexerFromFilename(filename string) string {
return chromaLexerFromType(ext) return chromaLexerFromType(ext)
} }
func locateErrorInString(src string, matcher LineMatcherFn) ErrorContext { func locateErrorInString(src string, matcher LineMatcherFn) (*ErrorContext, text.Position) {
return locateError(strings.NewReader(src), &fileError{}, matcher) return locateError(strings.NewReader(src), &fileError{}, matcher)
} }
func locateError(r io.Reader, le FileError, matches LineMatcherFn) ErrorContext { func locateError(r io.Reader, le FileError, matches LineMatcherFn) (*ErrorContext, text.Position) {
if le == nil { if le == nil {
panic("must provide an error") panic("must provide an error")
} }
errCtx := ErrorContext{position: text.Position{LineNumber: -1, ColumnNumber: 1, Offset: -1}, LinesPos: -1} errCtx := &ErrorContext{LinesPos: -1}
pos := text.Position{LineNumber: -1, ColumnNumber: 1, Offset: -1}
b, err := ioutil.ReadAll(r) b, err := ioutil.ReadAll(r)
if err != nil { if err != nil {
return errCtx return errCtx, pos
} }
pos := &errCtx.position
lepos := le.Position() lepos := le.Position()
lines := strings.Split(string(b), "\n") lines := strings.Split(string(b), "\n")
@ -262,5 +144,5 @@ func locateError(r io.Reader, le FileError, matches LineMatcherFn) ErrorContext
} }
return errCtx return errCtx, pos
} }

View file

@ -1,4 +1,4 @@
// Copyright 2018 The Hugo Authors. All rights reserved. // Copyright 2022 The Hugo Authors. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "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 not use this file except in compliance with the License.
@ -38,44 +38,48 @@ LINE 7
LINE 8 LINE 8
` `
location := locateErrorInString(lines, lineMatcher) location, pos := locateErrorInString(lines, lineMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"LINE 3", "LINE 4", "This is THEONE", "LINE 6", "LINE 7"}) c.Assert(location.Lines, qt.DeepEquals, []string{"LINE 3", "LINE 4", "This is THEONE", "LINE 6", "LINE 7"})
pos := location.Position()
c.Assert(pos.LineNumber, qt.Equals, 5) c.Assert(pos.LineNumber, qt.Equals, 5)
c.Assert(location.LinesPos, qt.Equals, 2) c.Assert(location.LinesPos, qt.Equals, 2)
c.Assert(locateErrorInString(`This is THEONE`, lineMatcher).Lines, qt.DeepEquals, []string{"This is THEONE"}) locate := func(s string, m LineMatcherFn) *ErrorContext {
ctx, _ := locateErrorInString(s, m)
return ctx
}
location = locateErrorInString(`L1 c.Assert(locate(`This is THEONE`, lineMatcher).Lines, qt.DeepEquals, []string{"This is THEONE"})
location, pos = locateErrorInString(`L1
This is THEONE This is THEONE
L2 L2
`, lineMatcher) `, lineMatcher)
c.Assert(location.Position().LineNumber, qt.Equals, 2) c.Assert(pos.LineNumber, qt.Equals, 2)
c.Assert(location.LinesPos, qt.Equals, 1) c.Assert(location.LinesPos, qt.Equals, 1)
c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "This is THEONE", "L2", ""}) c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "This is THEONE", "L2", ""})
location = locateErrorInString(`This is THEONE location = locate(`This is THEONE
L2 L2
`, lineMatcher) `, lineMatcher)
c.Assert(location.LinesPos, qt.Equals, 0) c.Assert(location.LinesPos, qt.Equals, 0)
c.Assert(location.Lines, qt.DeepEquals, []string{"This is THEONE", "L2", ""}) c.Assert(location.Lines, qt.DeepEquals, []string{"This is THEONE", "L2", ""})
location = locateErrorInString(`L1 location = locate(`L1
This THEONE This THEONE
`, lineMatcher) `, lineMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "This THEONE", ""}) c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "This THEONE", ""})
c.Assert(location.LinesPos, qt.Equals, 1) c.Assert(location.LinesPos, qt.Equals, 1)
location = locateErrorInString(`L1 location = locate(`L1
L2 L2
This THEONE This THEONE
`, lineMatcher) `, lineMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "L2", "This THEONE", ""}) c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "L2", "This THEONE", ""})
c.Assert(location.LinesPos, qt.Equals, 2) c.Assert(location.LinesPos, qt.Equals, 2)
location = locateErrorInString("NO MATCH", lineMatcher) location, pos = locateErrorInString("NO MATCH", lineMatcher)
c.Assert(location.Position().LineNumber, qt.Equals, -1) c.Assert(pos.LineNumber, qt.Equals, -1)
c.Assert(location.LinesPos, qt.Equals, -1) c.Assert(location.LinesPos, qt.Equals, -1)
c.Assert(len(location.Lines), qt.Equals, 0) c.Assert(len(location.Lines), qt.Equals, 0)
@ -83,7 +87,7 @@ This THEONE
return m.LineNumber == 6 return m.LineNumber == 6
} }
location = locateErrorInString(`A location, pos = locateErrorInString(`A
B B
C C
D D
@ -95,7 +99,7 @@ I
J`, lineMatcher) J`, lineMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"D", "E", "F", "G", "H"}) c.Assert(location.Lines, qt.DeepEquals, []string{"D", "E", "F", "G", "H"})
c.Assert(location.Position().LineNumber, qt.Equals, 6) c.Assert(pos.LineNumber, qt.Equals, 6)
c.Assert(location.LinesPos, qt.Equals, 2) c.Assert(location.LinesPos, qt.Equals, 2)
// Test match EOF // Test match EOF
@ -103,26 +107,26 @@ J`, lineMatcher)
return m.LineNumber == 4 return m.LineNumber == 4
} }
location = locateErrorInString(`A location, pos = locateErrorInString(`A
B B
C C
`, lineMatcher) `, lineMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"B", "C", ""}) c.Assert(location.Lines, qt.DeepEquals, []string{"B", "C", ""})
c.Assert(location.Position().LineNumber, qt.Equals, 4) c.Assert(pos.LineNumber, qt.Equals, 4)
c.Assert(location.LinesPos, qt.Equals, 2) c.Assert(location.LinesPos, qt.Equals, 2)
offsetMatcher := func(m LineMatcher) bool { offsetMatcher := func(m LineMatcher) bool {
return m.Offset == 1 return m.Offset == 1
} }
location = locateErrorInString(`A location, pos = locateErrorInString(`A
B B
C C
D D
E`, offsetMatcher) E`, offsetMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"A", "B", "C", "D"}) c.Assert(location.Lines, qt.DeepEquals, []string{"A", "B", "C", "D"})
c.Assert(location.Position().LineNumber, qt.Equals, 2) c.Assert(pos.LineNumber, qt.Equals, 2)
c.Assert(location.LinesPos, qt.Equals, 1) c.Assert(location.LinesPos, qt.Equals, 1)
} }

View file

@ -19,37 +19,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"os"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
"strconv" "strconv"
_errors "github.com/pkg/errors"
) )
// As defined in https://godoc.org/github.com/pkg/errors
type causer interface {
Cause() error
}
type stackTracer interface {
StackTrace() _errors.StackTrace
}
// PrintStackTraceFromErr prints the error's stack trace to stdoud.
func PrintStackTraceFromErr(err error) {
FprintStackTraceFromErr(os.Stdout, err)
}
// FprintStackTraceFromErr prints the error's stack trace to w.
func FprintStackTraceFromErr(w io.Writer, err error) {
if err, ok := err.(stackTracer); ok {
for _, f := range err.StackTrace() {
fmt.Fprintf(w, "%+s:%d\n", f, f)
}
}
}
// PrintStackTrace prints the current stacktrace to w. // PrintStackTrace prints the current stacktrace to w.
func PrintStackTrace(w io.Writer) { func PrintStackTrace(w io.Writer) {
buf := make([]byte, 1<<16) buf := make([]byte, 1<<16)

View file

@ -1,11 +1,11 @@
// Copyright 2018 The Hugo Authors. All rights reserved. // Copyright 2022 The Hugo Authors. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "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 not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable lfmtaw or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
@ -15,59 +15,217 @@ package herrors
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io"
"path/filepath"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/common/text" "github.com/gohugoio/hugo/common/text"
"github.com/pelletier/go-toml/v2"
"github.com/spf13/afero"
"github.com/tdewolff/parse/v2"
"github.com/pkg/errors" "errors"
) )
var _ causer = (*fileError)(nil)
// FileError represents an error when handling a file: Parsing a config file, // FileError represents an error when handling a file: Parsing a config file,
// execute a template etc. // execute a template etc.
type FileError interface { type FileError interface {
error error
// ErroContext holds some context information about the error.
ErrorContext() *ErrorContext
text.Positioner text.Positioner
// A string identifying the type of file, e.g. JSON, TOML, markdown etc. // UpdatePosition updates the position of the error.
Type() string UpdatePosition(pos text.Position) FileError
// UpdateContent updates the error with a new ErrorContext from the content of the file.
UpdateContent(r io.Reader, linematcher LineMatcherFn) FileError
} }
var _ FileError = (*fileError)(nil) // Unwrapper can unwrap errors created with fmt.Errorf.
type Unwrapper interface {
Unwrap() error
}
var (
_ FileError = (*fileError)(nil)
_ Unwrapper = (*fileError)(nil)
)
func (fe *fileError) UpdatePosition(pos text.Position) FileError {
oldFilename := fe.Position().Filename
if pos.Filename != "" && fe.fileType == "" {
_, fe.fileType = paths.FileAndExtNoDelimiter(filepath.Clean(pos.Filename))
}
if pos.Filename == "" {
pos.Filename = oldFilename
}
fe.position = pos
return fe
}
func (fe *fileError) UpdateContent(r io.Reader, linematcher LineMatcherFn) FileError {
if linematcher == nil {
linematcher = SimpleLineMatcher
}
var (
contentPos text.Position
posle = fe.position
errorContext *ErrorContext
)
if posle.LineNumber <= 1 && posle.Offset > 0 {
// Try to locate the line number from the content if offset is set.
errorContext, contentPos = locateError(r, fe, func(m LineMatcher) bool {
if posle.Offset >= m.Offset && posle.Offset < m.Offset+len(m.Line) {
lno := posle.LineNumber - m.Position.LineNumber + m.LineNumber
m.Position = text.Position{LineNumber: lno}
return linematcher(m)
}
return false
})
} else {
errorContext, contentPos = locateError(r, fe, linematcher)
}
if errorContext.ChromaLexer == "" {
if fe.fileType != "" {
errorContext.ChromaLexer = chromaLexerFromType(fe.fileType)
} else {
errorContext.ChromaLexer = chromaLexerFromFilename(fe.Position().Filename)
}
}
fe.errorContext = errorContext
if contentPos.LineNumber > 0 {
fe.position.LineNumber = contentPos.LineNumber
}
return fe
}
type fileError struct { type fileError struct {
position text.Position position text.Position
errorContext *ErrorContext
fileType string fileType string
cause error cause error
} }
type fileErrorWithErrorContext struct {
*fileError
}
func (e *fileError) ErrorContext() *ErrorContext {
return e.errorContext
}
// Position returns the text position of this error. // Position returns the text position of this error.
func (e fileError) Position() text.Position { func (e fileError) Position() text.Position {
return e.position return e.position
} }
func (e *fileError) Type() string {
return e.fileType
}
func (e *fileError) Error() string { func (e *fileError) Error() string {
if e.cause == nil { return fmt.Sprintf("%s: %s", e.position, e.cause)
return "" }
func (e *fileError) Unwrap() error {
return e.cause
}
// NewFileError creates a new FileError that wraps err.
// The value for name should identify the file, the best
// being the full filename to the file on disk.
func NewFileError(name string, err error) FileError {
if err == nil {
panic("err is nil")
} }
return e.cause.Error()
}
func (f *fileError) Cause() error { // Filetype is used to determine the Chroma lexer to use.
return f.cause fileType, pos := extractFileTypePos(err)
} pos.Filename = name
if fileType == "" {
_, fileType = paths.FileAndExtNoDelimiter(filepath.Clean(name))
}
if pos.LineNumber < 0 {
panic(fmt.Sprintf("invalid line number: %d", pos.LineNumber))
}
// NewFileError creates a new FileError.
func NewFileError(fileType string, offset, lineNumber, columnNumber int, err error) FileError {
pos := text.Position{Offset: offset, LineNumber: lineNumber, ColumnNumber: columnNumber}
return &fileError{cause: err, fileType: fileType, position: pos} return &fileError{cause: err, fileType: fileType, position: pos}
}
// NewFileErrorFromFile is a convenience method to create a new FileError from a file.
func NewFileErrorFromFile(err error, filename, realFilename string, fs afero.Fs, linematcher LineMatcherFn) FileError {
if err == nil {
panic("err is nil")
}
if linematcher == nil {
linematcher = SimpleLineMatcher
}
f, err2 := fs.Open(filename)
if err2 != nil {
return NewFileError(realFilename, err)
}
defer f.Close()
return NewFileError(realFilename, err).UpdateContent(f, linematcher)
}
// Cause returns the underlying error or itself if it does not implement Unwrap.
func Cause(err error) error {
if u := errors.Unwrap(err); u != nil {
return u
}
return err
}
func extractFileTypePos(err error) (string, text.Position) {
err = Cause(err)
var fileType string
// Fall back to line/col 1:1 if we cannot find any better information.
pos := text.Position{
Offset: -1,
LineNumber: 1,
ColumnNumber: 1,
}
// JSON errors.
offset, typ := extractOffsetAndType(err)
if fileType == "" {
fileType = typ
}
if offset >= 0 {
pos.Offset = offset
}
// The error type from the minifier contains line number and column number.
if line, col := exctractLineNumberAndColumnNumber(err); line >= 0 {
pos.LineNumber = line
pos.ColumnNumber = col
return fileType, pos
}
// Look in the error message for the line number.
for _, handle := range lineNumberExtractors {
lno, col := handle(err)
if lno > 0 {
pos.ColumnNumber = col
pos.LineNumber = lno
break
}
}
return fileType, pos
} }
// UnwrapFileError tries to unwrap a FileError from err. // UnwrapFileError tries to unwrap a FileError from err.
@ -77,49 +235,26 @@ func UnwrapFileError(err error) FileError {
switch v := err.(type) { switch v := err.(type) {
case FileError: case FileError:
return v return v
case causer:
err = v.Cause()
default: default:
return nil err = errors.Unwrap(err)
} }
} }
return nil return nil
} }
// ToFileErrorWithOffset will return a new FileError with a line number // UnwrapFileErrorsWithErrorContext tries to unwrap all FileError in err that has an ErrorContext.
// with the given offset from the original. func UnwrapFileErrorsWithErrorContext(err error) []FileError {
func ToFileErrorWithOffset(fe FileError, offset int) FileError { var errs []FileError
pos := fe.Position() for err != nil {
return ToFileErrorWithLineNumber(fe, pos.LineNumber+offset) if v, ok := err.(FileError); ok && v.ErrorContext() != nil {
} errs = append(errs, v)
// ToFileErrorWithOffset will return a new FileError with the given line number.
func ToFileErrorWithLineNumber(fe FileError, lineNumber int) FileError {
pos := fe.Position()
pos.LineNumber = lineNumber
return &fileError{cause: fe, fileType: fe.Type(), position: pos}
}
// ToFileError will convert the given error to an error supporting
// the FileError interface.
func ToFileError(fileType string, err error) FileError {
for _, handle := range lineNumberExtractors {
lno, col := handle(err)
offset, typ := extractOffsetAndType(err)
if fileType == "" {
fileType = typ
} }
err = errors.Unwrap(err)
if lno > 0 || offset != -1 {
return NewFileError(fileType, offset, lno, col, err)
} }
} return errs
// Fall back to the pointing to line number 1.
return NewFileError(fileType, -1, 1, 1, err)
} }
func extractOffsetAndType(e error) (int, string) { func extractOffsetAndType(e error) (int, string) {
e = errors.Cause(e)
switch v := e.(type) { switch v := e.(type) {
case *json.UnmarshalTypeError: case *json.UnmarshalTypeError:
return int(v.Offset), "json" return int(v.Offset), "json"
@ -129,3 +264,15 @@ func extractOffsetAndType(e error) (int, string) {
return -1, "" return -1, ""
} }
} }
func exctractLineNumberAndColumnNumber(e error) (int, int) {
switch v := e.(type) {
case *parse.Error:
return v.Line, v.Column
case *toml.DecodeError:
return v.Position()
}
return -1, -1
}

View file

@ -1,4 +1,4 @@
// Copyright 2018 The Hugo Authors. All rights reserved. // Copyright 2022 The Hugo Authors. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "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 not use this file except in compliance with the License.
@ -14,14 +14,44 @@
package herrors package herrors
import ( import (
"fmt"
"strings"
"testing" "testing"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/common/text"
qt "github.com/frankban/quicktest" qt "github.com/frankban/quicktest"
) )
func TestToLineNumberError(t *testing.T) { func TestNewFileError(t *testing.T) {
t.Parallel()
c := qt.New(t)
fe := NewFileError("foo.html", errors.New("bar"))
c.Assert(fe.Error(), qt.Equals, `"foo.html:1:1": bar`)
lines := ""
for i := 1; i <= 100; i++ {
lines += fmt.Sprintf("line %d\n", i)
}
fe.UpdatePosition(text.Position{LineNumber: 32, ColumnNumber: 2})
c.Assert(fe.Error(), qt.Equals, `"foo.html:32:2": bar`)
fe.UpdatePosition(text.Position{LineNumber: 0, ColumnNumber: 0, Offset: 212})
fe.UpdateContent(strings.NewReader(lines), SimpleLineMatcher)
c.Assert(fe.Error(), qt.Equals, `"foo.html:32:0": bar`)
errorContext := fe.ErrorContext()
c.Assert(errorContext, qt.IsNotNil)
c.Assert(errorContext.Lines, qt.DeepEquals, []string{"line 30", "line 31", "line 32", "line 33", "line 34"})
c.Assert(errorContext.LinesPos, qt.Equals, 2)
c.Assert(errorContext.ChromaLexer, qt.Equals, "go-html-template")
}
func TestNewFileErrorExtractFromMessage(t *testing.T) {
t.Parallel() t.Parallel()
c := qt.New(t) c := qt.New(t)
@ -37,18 +67,16 @@ func TestToLineNumberError(t *testing.T) {
{errors.New("parse failed: template: _default/bundle-resource-meta.html:11: unexpected in operand"), 0, 11, 1}, {errors.New("parse failed: template: _default/bundle-resource-meta.html:11: unexpected in operand"), 0, 11, 1},
{errors.New(`failed:: template: _default/bundle-resource-meta.html:2:7: executing "main" at <.Titles>`), 0, 2, 7}, {errors.New(`failed:: template: _default/bundle-resource-meta.html:2:7: executing "main" at <.Titles>`), 0, 2, 7},
{errors.New(`failed to load translations: (6, 7): was expecting token =, but got "g" instead`), 0, 6, 7}, {errors.New(`failed to load translations: (6, 7): was expecting token =, but got "g" instead`), 0, 6, 7},
{errors.New(`execute of template failed: template: index.html:2:5: executing "index.html" at <partial "foo.html" .>: error calling partial: "/layouts/partials/foo.html:3:6": execute of template failed: template: partials/foo.html:3:6: executing "partials/foo.html" at <.ThisDoesNotExist>: can't evaluate field ThisDoesNotExist in type *hugolib.pageStat`), 0, 2, 5},
} { } {
got := ToFileError("template", test.in) got := NewFileError("test.txt", test.in)
errMsg := qt.Commentf("[%d][%T]", i, got) errMsg := qt.Commentf("[%d][%T]", i, got)
le, ok := got.(FileError)
c.Assert(ok, qt.Equals, true)
c.Assert(ok, qt.Equals, true, errMsg) pos := got.Position()
pos := le.Position()
c.Assert(pos.LineNumber, qt.Equals, test.lineNumber, errMsg) c.Assert(pos.LineNumber, qt.Equals, test.lineNumber, errMsg)
c.Assert(pos.ColumnNumber, qt.Equals, test.columnNumber, errMsg) c.Assert(pos.ColumnNumber, qt.Equals, test.columnNumber, errMsg)
c.Assert(errors.Cause(got), qt.Not(qt.IsNil)) c.Assert(errors.Unwrap(got), qt.Not(qt.IsNil))
} }
} }

View file

@ -16,36 +16,22 @@ package herrors
import ( import (
"regexp" "regexp"
"strconv" "strconv"
"github.com/pkg/errors"
"github.com/pelletier/go-toml/v2"
) )
var lineNumberExtractors = []lineNumberExtractor{ var lineNumberExtractors = []lineNumberExtractor{
// Template/shortcode parse errors // Template/shortcode parse errors
newLineNumberErrHandlerFromRegexp(".*:(\\d+):(\\d*):"), newLineNumberErrHandlerFromRegexp(`:(\d+):(\d*):`),
newLineNumberErrHandlerFromRegexp(".*:(\\d+):"), newLineNumberErrHandlerFromRegexp(`:(\d+):`),
// TOML parse errors
tomlLineNumberExtractor,
// YAML parse errors // YAML parse errors
newLineNumberErrHandlerFromRegexp("line (\\d+):"), newLineNumberErrHandlerFromRegexp(`line (\d+):`),
// i18n bundle errors // i18n bundle errors
newLineNumberErrHandlerFromRegexp("\\((\\d+),\\s(\\d*)"), newLineNumberErrHandlerFromRegexp(`\((\d+),\s(\d*)`),
} }
type lineNumberExtractor func(e error) (int, int) type lineNumberExtractor func(e error) (int, int)
var tomlLineNumberExtractor = func(e error) (int, int) {
e = errors.Cause(e)
if terr, ok := e.(*toml.DecodeError); ok {
return terr.Position()
}
return -1, -1
}
func newLineNumberErrHandlerFromRegexp(expression string) lineNumberExtractor { func newLineNumberErrHandlerFromRegexp(expression string) lineNumberExtractor {
re := regexp.MustCompile(expression) re := regexp.MustCompile(expression)
return extractLineNo(re) return extractLineNo(re)
@ -72,6 +58,6 @@ func extractLineNo(re *regexp.Regexp) lineNumberExtractor {
return lno, col return lno, col
} }
return -1, col return 0, col
} }
} }

View file

@ -14,13 +14,12 @@
package hugio package hugio
import ( import (
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -60,7 +59,7 @@ func CopyDir(fs afero.Fs, from, to string, shouldCopy func(filename string) bool
} }
if !fi.IsDir() { if !fi.IsDir() {
return errors.Errorf("%q is not a directory", from) return fmt.Errorf("%q is not a directory", from)
} }
err = fs.MkdirAll(to, 0777) // before umask err = fs.MkdirAll(to, 0777) // before umask

View file

@ -14,12 +14,11 @@
package config package config
import ( import (
"fmt"
"sort" "sort"
"strings" "strings"
"sync" "sync"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/types"
"github.com/gobwas/glob" "github.com/gobwas/glob"
@ -207,7 +206,7 @@ func DecodeServer(cfg Provider) (*Server, error) {
// There are some tricky infinite loop situations when dealing // There are some tricky infinite loop situations when dealing
// when the target does not have a trailing slash. // when the target does not have a trailing slash.
// This can certainly be handled better, but not time for that now. // This can certainly be handled better, but not time for that now.
return nil, errors.Errorf("unsupported redirect to value %q in server config; currently this must be either a remote destination or a local folder, e.g. \"/blog/\" or \"/blog/index.html\"", redir.To) return nil, fmt.Errorf("unsupported redirect to value %q in server config; currently this must be either a remote destination or a local folder, e.g. \"/blog/\" or \"/blog/index.html\"", redir.To)
} }
s.Redirects[i] = redir s.Redirects[i] = redir
} }

View file

@ -14,14 +14,13 @@
package config package config
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
@ -60,7 +59,7 @@ func FromConfigString(config, configType string) (Provider, error) {
func FromFile(fs afero.Fs, filename string) (Provider, error) { func FromFile(fs afero.Fs, filename string) (Provider, error) {
m, err := loadConfigFromFile(fs, filename) m, err := loadConfigFromFile(fs, filename)
if err != nil { if err != nil {
return nil, herrors.WithFileContextForFileDefault(err, filename, fs) return nil, herrors.NewFileErrorFromFile(err, filename, filename, fs, herrors.SimpleLineMatcher)
} }
return NewFrom(m), nil return NewFrom(m), nil
} }
@ -132,7 +131,7 @@ func LoadConfigFromDir(sourceFs afero.Fs, configDir, environment string) (Provid
if err != nil { if err != nil {
// This will be used in error reporting, use the most specific value. // This will be used in error reporting, use the most specific value.
dirnames = []string{path} dirnames = []string{path}
return errors.Wrapf(err, "failed to unmarshl config for path %q", path) return fmt.Errorf("failed to unmarshl config for path %q: %w", path, err)
} }
var keyPath []string var keyPath []string

View file

@ -27,7 +27,7 @@ import (
"github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/paths"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
@ -94,11 +94,11 @@ func NewContent(h *hugolib.HugoSites, kind, targetPath string) error {
} }
if ext == "" { if ext == "" {
return "", errors.Errorf("failed to resolve %q to a archetype template", targetPath) return "", fmt.Errorf("failed to resolve %q to a archetype template", targetPath)
} }
if !files.IsContentFile(b.targetPath) { if !files.IsContentFile(b.targetPath) {
return "", errors.Errorf("target path %q is not a known content format", b.targetPath) return "", fmt.Errorf("target path %q is not a known content format", b.targetPath)
} }
return b.buildFile() return b.buildFile()
@ -188,14 +188,14 @@ func (b *contentBuilder) buildDir() error {
in, err := meta.Open() in, err := meta.Open()
if err != nil { if err != nil {
return errors.Wrap(err, "failed to open non-content file") return fmt.Errorf("failed to open non-content file: %w", err)
} }
targetFilename := filepath.Join(baseDir, b.targetPath, strings.TrimPrefix(filename, b.archetypeFilename)) targetFilename := filepath.Join(baseDir, b.targetPath, strings.TrimPrefix(filename, b.archetypeFilename))
targetDir := filepath.Dir(targetFilename) targetDir := filepath.Dir(targetFilename)
if err := b.sourceFs.MkdirAll(targetDir, 0o777); err != nil && !os.IsExist(err) { if err := b.sourceFs.MkdirAll(targetDir, 0o777); err != nil && !os.IsExist(err) {
return errors.Wrapf(err, "failed to create target directory for %q", targetDir) return fmt.Errorf("failed to create target directory for %q: %w", targetDir, err)
} }
out, err := b.sourceFs.Create(targetFilename) out, err := b.sourceFs.Create(targetFilename)
@ -329,7 +329,7 @@ func (b *contentBuilder) mapArcheTypeDir() error {
w := hugofs.NewWalkway(walkCfg) w := hugofs.NewWalkway(walkCfg)
if err := w.Walk(); err != nil { if err := w.Walk(); err != nil {
return errors.Wrapf(err, "failed to walk archetype dir %q", b.archetypeFilename) return fmt.Errorf("failed to walk archetype dir %q: %w", b.archetypeFilename, err)
} }
b.dirMap = m b.dirMap = m
@ -374,7 +374,7 @@ func (b *contentBuilder) usesSiteVar(filename string) (bool, error) {
} }
bb, err := afero.ReadFile(b.archeTypeFs, filename) bb, err := afero.ReadFile(b.archeTypeFs, filename)
if err != nil { if err != nil {
return false, errors.Wrap(err, "failed to open archetype file") return false, fmt.Errorf("failed to open archetype file: %w", err)
} }
return bytes.Contains(bb, []byte(".Site")) || bytes.Contains(bb, []byte("site.")), nil return bytes.Contains(bb, []byte(".Site")) || bytes.Contains(bb, []byte("site.")), nil

View file

@ -34,11 +34,12 @@ import (
"strings" "strings"
"sync" "sync"
"errors"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/gobwas/glob" "github.com/gobwas/glob"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"golang.org/x/text/unicode/norm" "golang.org/x/text/unicode/norm"

View file

@ -20,12 +20,13 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"errors"
"github.com/gobwas/glob" "github.com/gobwas/glob"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
hglob "github.com/gohugoio/hugo/hugofs/glob" hglob "github.com/gohugoio/hugo/hugofs/glob"
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
) )
const deploymentConfigKey = "deployment" const deploymentConfigKey = "deployment"

13
deps/deps.go vendored
View file

@ -1,12 +1,11 @@
package deps package deps
import ( import (
"fmt"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/common/loggers"
@ -186,11 +185,11 @@ func (d *Deps) SetTextTmpl(tmpl tpl.TemplateParseFinder) {
func (d *Deps) LoadResources() error { func (d *Deps) LoadResources() error {
// Note that the translations need to be loaded before the templates. // Note that the translations need to be loaded before the templates.
if err := d.translationProvider.Update(d); err != nil { if err := d.translationProvider.Update(d); err != nil {
return errors.Wrap(err, "loading translations") return fmt.Errorf("loading translations: %w", err)
} }
if err := d.templateProvider.Update(d); err != nil { if err := d.templateProvider.Update(d); err != nil {
return errors.Wrap(err, "loading templates") return fmt.Errorf("loading templates: %w", err)
} }
return nil return nil
@ -236,18 +235,18 @@ func New(cfg DepsCfg) (*Deps, error) {
securityConfig, err := security.DecodeConfig(cfg.Cfg) securityConfig, err := security.DecodeConfig(cfg.Cfg)
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "failed to create security config from configuration") return nil, fmt.Errorf("failed to create security config from configuration: %w", err)
} }
execHelper := hexec.New(securityConfig) execHelper := hexec.New(securityConfig)
ps, err := helpers.NewPathSpec(fs, cfg.Language, logger) ps, err := helpers.NewPathSpec(fs, cfg.Language, logger)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "create PathSpec") return nil, fmt.Errorf("create PathSpec: %w", err)
} }
fileCaches, err := filecache.NewCaches(ps) fileCaches, err := filecache.NewCaches(ps)
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "failed to create file caches from configuration") return nil, fmt.Errorf("failed to create file caches from configuration: %w", err)
} }
errorHandler := &globalErrHandler{} errorHandler := &globalErrHandler{}

View file

@ -31,7 +31,6 @@ import (
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/hugio"
_errors "github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -403,7 +402,7 @@ func GetCacheDir(fs afero.Fs, cfg config.Provider) (string, error) {
if !exists { if !exists {
err := fs.MkdirAll(cacheDir, 0777) // Before umask err := fs.MkdirAll(cacheDir, 0777) // Before umask
if err != nil { if err != nil {
return "", _errors.Wrap(err, "failed to create cache dir") return "", fmt.Errorf("failed to create cache dir: %w", err)
} }
} }
return cacheDir, nil return cacheDir, nil

View file

@ -14,12 +14,11 @@
package hugofs package hugofs
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -232,7 +231,7 @@ func (l *baseFileDecoratorFile) Readdir(c int) (ofi []os.FileInfo, err error) {
} }
fi, err = l.fs.decorate(fi, filename) fi, err = l.fs.decorate(fi, filename)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "decorate") return nil, fmt.Errorf("decorate: %w", err)
} }
fisp = append(fisp, fi) fisp = append(fisp, fi)
} }

View file

@ -28,7 +28,7 @@ import (
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
"golang.org/x/text/unicode/norm" "golang.org/x/text/unicode/norm"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/common/hreflect" "github.com/gohugoio/hugo/common/hreflect"

View file

@ -21,8 +21,6 @@ import (
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
"github.com/pkg/errors"
radix "github.com/armon/go-radix" radix "github.com/armon/go-radix"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -191,7 +189,7 @@ func (fs *RootMappingFs) Dirs(base string) ([]FileMetaInfo, error) {
fs = decorateDirs(fs, r.Meta) fs = decorateDirs(fs, r.Meta)
fi, err := fs.Stat("") fi, err := fs.Stat("")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "RootMappingFs.Dirs") return nil, fmt.Errorf("RootMappingFs.Dirs: %w", err)
} }
if !fi.IsDir() { if !fi.IsDir() {
@ -560,7 +558,7 @@ func (fs *RootMappingFs) doLstat(name string) ([]FileMetaInfo, error) {
if fileCount > 1 { if fileCount > 1 {
// Not supported by this filesystem. // Not supported by this filesystem.
return nil, errors.Errorf("found multiple files with name %q, use .Readdir or the source filesystem directly", name) return nil, fmt.Errorf("found multiple files with name %q, use .Readdir or the source filesystem directly", name)
} }
return []FileMetaInfo{roots[0].fi}, nil return []FileMetaInfo{roots[0].fi}, nil

View file

@ -14,11 +14,12 @@
package hugofs package hugofs
import ( import (
"fmt"
"os" "os"
"syscall" "syscall"
"time" "time"
"github.com/pkg/errors" "errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -83,7 +84,7 @@ func (fs *SliceFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
return decorateFileInfo(fi, fs, fs.getOpener(name), "", "", nil), false, nil return decorateFileInfo(fi, fs, fs.getOpener(name), "", "", nil), false, nil
} }
return nil, false, errors.Errorf("lstat: files not supported: %q", name) return nil, false, fmt.Errorf("lstat: files not supported: %q", name)
} }
func (fs *SliceFs) Mkdir(n string, p os.FileMode) error { func (fs *SliceFs) Mkdir(n string, p os.FileMode) error {

View file

@ -22,7 +22,7 @@ import (
"github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/common/loggers"
"github.com/pkg/errors" "errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -125,7 +125,7 @@ func (w *Walkway) Walk() error {
if w.checkErr(w.root, err) { if w.checkErr(w.root, err) {
return nil return nil
} }
return w.walkFn(w.root, nil, errors.Wrapf(err, "walk: %q", w.root)) return w.walkFn(w.root, nil, fmt.Errorf("walk: %q: %w", w.root, err))
} }
fi = info.(FileMetaInfo) fi = info.(FileMetaInfo)
} }
@ -192,7 +192,7 @@ func (w *Walkway) walk(path string, info FileMetaInfo, dirEntries []FileMetaInfo
if w.checkErr(path, err) { if w.checkErr(path, err) {
return nil return nil
} }
return walkFn(path, info, errors.Wrapf(err, "walk: open %q (%q)", path, w.root)) return walkFn(path, info, fmt.Errorf("walk: open %q (%q): %w", path, w.root, err))
} }
fis, err := f.Readdir(-1) fis, err := f.Readdir(-1)
@ -201,7 +201,7 @@ func (w *Walkway) walk(path string, info FileMetaInfo, dirEntries []FileMetaInfo
if w.checkErr(filename, err) { if w.checkErr(filename, err) {
return nil return nil
} }
return walkFn(path, info, errors.Wrap(err, "walk: Readdir")) return walkFn(path, info, fmt.Errorf("walk: Readdir: %w", err))
} }
dirEntries = fileInfosToFileMetaInfos(fis) dirEntries = fileInfosToFileMetaInfos(fis)

View file

@ -22,7 +22,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/common/para" "github.com/gohugoio/hugo/common/para"
"github.com/gohugoio/hugo/htesting" "github.com/gohugoio/hugo/htesting"

View file

@ -33,11 +33,12 @@ import (
"github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/parser/metadecoders"
"errors"
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/modules" "github.com/gohugoio/hugo/modules"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/config/privacy" "github.com/gohugoio/hugo/config/privacy"
@ -510,5 +511,5 @@ func (configLoader) loadSiteConfig(cfg config.Provider) (scfg SiteConfig, err er
} }
func (l configLoader) wrapFileError(err error, filename string) error { func (l configLoader) wrapFileError(err error, filename string) error {
return herrors.WithFileContextForFileDefault(err, filename, l.Fs) return herrors.NewFileErrorFromFile(err, filename, filename, l.Fs, herrors.SimpleLineMatcher)
} }

View file

@ -146,7 +146,7 @@ baseURL = "https://example.org"
_, _, err := LoadConfig(ConfigSourceDescriptor{Fs: mm, Environment: "development", Filename: "hugo.toml", AbsConfigDir: "config"}) _, _, err := LoadConfig(ConfigSourceDescriptor{Fs: mm, Environment: "development", Filename: "hugo.toml", AbsConfigDir: "config"})
c.Assert(err, qt.Not(qt.IsNil)) c.Assert(err, qt.Not(qt.IsNil))
fe := herrors.UnwrapErrorWithFileContext(err) fe := herrors.UnwrapFileError(err)
c.Assert(fe, qt.Not(qt.IsNil)) c.Assert(fe, qt.Not(qt.IsNil))
c.Assert(fe.Position().Filename, qt.Equals, filepath.FromSlash("config/development/config.toml")) c.Assert(fe.Position().Filename, qt.Equals, filepath.FromSlash("config/development/config.toml"))
} }

View file

@ -14,6 +14,7 @@
package hugolib package hugolib
import ( import (
"fmt"
"io" "io"
"path/filepath" "path/filepath"
"strings" "strings"
@ -25,7 +26,6 @@ import (
"github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/page"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -48,12 +48,12 @@ func (f ContentFactory) ApplyArchetypeFilename(w io.Writer, p page.Page, archety
} }
if fi.IsDir() { if fi.IsDir() {
return errors.Errorf("archetype directory (%q) not supported", archetypeFilename) return fmt.Errorf("archetype directory (%q) not supported", archetypeFilename)
} }
templateSource, err := afero.ReadFile(f.h.SourceFilesystems.Archetypes.Fs, archetypeFilename) templateSource, err := afero.ReadFile(f.h.SourceFilesystems.Archetypes.Fs, archetypeFilename)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to read archetype file %q: %s", archetypeFilename, err) return fmt.Errorf("failed to read archetype file %q: %s: %w", archetypeFilename, err, err)
} }
@ -79,12 +79,12 @@ func (f ContentFactory) ApplyArchetypeTemplate(w io.Writer, p page.Page, archety
templ, err := ps.s.TextTmpl().Parse("archetype.md", string(templateSource)) templ, err := ps.s.TextTmpl().Parse("archetype.md", string(templateSource))
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to parse archetype template: %s", err) return fmt.Errorf("failed to parse archetype template: %s: %w", err, err)
} }
result, err := executeToString(ps.s.Tmpl(), templ, d) result, err := executeToString(ps.s.Tmpl(), templ, d)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to execute archetype template: %s", err) return fmt.Errorf("failed to execute archetype template: %s: %w", err, err)
} }
_, err = io.WriteString(w, f.shortcodeReplacerPost.Replace(result)) _, err = io.WriteString(w, f.shortcodeReplacerPost.Replace(result))

View file

@ -23,7 +23,6 @@ import (
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/page"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
@ -207,7 +206,7 @@ func (b *cmInsertKeyBuilder) WithFile(fi hugofs.FileMetaInfo) *cmInsertKeyBuilde
p, k := b.getBundle(p) p, k := b.getBundle(p)
if k == "" { if k == "" {
b.err = errors.Errorf("no bundle header found for %q", bundlePath) b.err = fmt.Errorf("no bundle header found for %q", bundlePath)
return b return b
} }

View file

@ -35,7 +35,6 @@ import (
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/gohugoio/hugo/common/para" "github.com/gohugoio/hugo/common/para"
"github.com/pkg/errors"
) )
func newPageMaps(h *HugoSites) *pageMaps { func newPageMaps(h *HugoSites) *pageMaps {
@ -131,13 +130,13 @@ func (m *pageMap) newPageFromContentNode(n *contentNode, parentBucket *pagesMapB
gi, err := s.h.gitInfoForPage(ps) gi, err := s.h.gitInfoForPage(ps)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to load Git data") return nil, fmt.Errorf("failed to load Git data: %w", err)
} }
ps.gitInfo = gi ps.gitInfo = gi
owners, err := s.h.codeownersForPage(ps) owners, err := s.h.codeownersForPage(ps)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to load CODEOWNERS") return nil, fmt.Errorf("failed to load CODEOWNERS: %w", err)
} }
ps.codeowners = owners ps.codeowners = owners
@ -282,7 +281,7 @@ func (m *pageMap) createSiteTaxonomies() error {
} else { } else {
taxonomy := m.s.taxonomies[viewName.plural] taxonomy := m.s.taxonomies[viewName.plural]
if taxonomy == nil { if taxonomy == nil {
walkErr = errors.Errorf("missing taxonomy: %s", viewName.plural) walkErr = fmt.Errorf("missing taxonomy: %s", viewName.plural)
return true return true
} }
m.taxonomyEntries.WalkPrefix(s, func(ss string, v any) bool { m.taxonomyEntries.WalkPrefix(s, func(ss string, v any) bool {

View file

@ -14,12 +14,11 @@
package hugolib package hugolib
import ( import (
"fmt"
"strings" "strings"
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/spf13/afero" "github.com/spf13/afero"
@ -41,7 +40,7 @@ type fileInfo struct {
func (fi *fileInfo) Open() (afero.File, error) { func (fi *fileInfo) Open() (afero.File, error) {
f, err := fi.FileInfo().Meta().Open() f, err := fi.FileInfo().Meta().Open()
if err != nil { if err != nil {
err = errors.Wrap(err, "fileInfo") err = fmt.Errorf("fileInfo: %w", err)
} }
return f, err return f, err

View file

@ -35,8 +35,6 @@ import (
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/modules" "github.com/gohugoio/hugo/modules"
hpaths "github.com/gohugoio/hugo/common/paths" hpaths "github.com/gohugoio/hugo/common/paths"
@ -176,7 +174,7 @@ func (b *BaseFs) AbsProjectContentDir(filename string) (string, string, error) {
} }
return "", "", errors.Errorf("could not determine content directory for %q", filename) return "", "", fmt.Errorf("could not determine content directory for %q", filename)
} }
// ResolveJSConfigFile resolves the JS-related config file to a absolute // ResolveJSConfigFile resolves the JS-related config file to a absolute
@ -468,7 +466,7 @@ func NewBase(p *paths.Paths, logger loggers.Logger, options ...func(*BaseFs) err
builder := newSourceFilesystemsBuilder(p, logger, b) builder := newSourceFilesystemsBuilder(p, logger, b)
sourceFilesystems, err := builder.Build() sourceFilesystems, err := builder.Build()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "build filesystems") return nil, fmt.Errorf("build filesystems: %w", err)
} }
b.SourceFilesystems = sourceFilesystems b.SourceFilesystems = sourceFilesystems
@ -502,7 +500,7 @@ func (b *sourceFilesystemsBuilder) Build() (*SourceFilesystems, error) {
if b.theBigFs == nil { if b.theBigFs == nil {
theBigFs, err := b.createMainOverlayFs(b.p) theBigFs, err := b.createMainOverlayFs(b.p)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "create main fs") return nil, fmt.Errorf("create main fs: %w", err)
} }
b.theBigFs = theBigFs b.theBigFs = theBigFs
@ -544,7 +542,7 @@ func (b *sourceFilesystemsBuilder) Build() (*SourceFilesystems, error) {
contentFs, err := hugofs.NewLanguageFs(b.p.LanguagesDefaultFirst.AsOrdinalSet(), contentBfs) contentFs, err := hugofs.NewLanguageFs(b.p.LanguagesDefaultFirst.AsOrdinalSet(), contentBfs)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "create content filesystem") return nil, fmt.Errorf("create content filesystem: %w", err)
} }
b.result.Content = b.newSourceFilesystem(files.ComponentFolderContent, contentFs, contentDirs) b.result.Content = b.newSourceFilesystem(files.ComponentFolderContent, contentFs, contentDirs)

View file

@ -15,6 +15,7 @@ package hugolib
import ( import (
"context" "context"
"fmt"
"io" "io"
"path/filepath" "path/filepath"
"sort" "sort"
@ -33,9 +34,10 @@ import (
"github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/output"
"github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/parser/metadecoders"
"errors"
"github.com/gohugoio/hugo/common/para" "github.com/gohugoio/hugo/common/para"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
@ -194,7 +196,7 @@ func (h *hugoSitesInit) Reset() {
func (h *HugoSites) Data() map[string]any { func (h *HugoSites) Data() map[string]any {
if _, err := h.init.data.Do(); err != nil { if _, err := h.init.data.Do(); err != nil {
h.SendError(errors.Wrap(err, "failed to load data")) h.SendError(fmt.Errorf("failed to load data: %w", err))
return nil return nil
} }
return h.data return h.data
@ -242,7 +244,7 @@ func (h *HugoSites) pickOneAndLogTheRest(errors []error) error {
for j, err := range errors { for j, err := range errors {
// If this is in server mode, we want to return an error to the client // If this is in server mode, we want to return an error to the client
// with a file context, if possible. // with a file context, if possible.
if herrors.UnwrapErrorWithFileContext(err) != nil { if herrors.UnwrapFileError(err) != nil {
i = j i = j
break break
} }
@ -327,7 +329,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) {
langConfig, err := newMultiLingualFromSites(cfg.Cfg, sites...) langConfig, err := newMultiLingualFromSites(cfg.Cfg, sites...)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to create language config") return nil, fmt.Errorf("failed to create language config: %w", err)
} }
var contentChangeTracker *contentChangeMap var contentChangeTracker *contentChangeMap
@ -365,7 +367,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) {
h.init.data.Add(func() (any, error) { h.init.data.Add(func() (any, error) {
err := h.loadData(h.PathSpec.BaseFs.Data.Dirs) err := h.loadData(h.PathSpec.BaseFs.Data.Dirs)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to load data") return nil, fmt.Errorf("failed to load data: %w", err)
} }
return nil, nil return nil, nil
}) })
@ -391,7 +393,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) {
h.init.gitInfo.Add(func() (any, error) { h.init.gitInfo.Add(func() (any, error) {
err := h.loadGitInfo() err := h.loadGitInfo()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to load Git info") return nil, fmt.Errorf("failed to load Git info: %w", err)
} }
return nil, nil return nil, nil
}) })
@ -402,7 +404,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) {
var l configLoader var l configLoader
if err := l.applyDeps(cfg, sites...); err != nil { if err := l.applyDeps(cfg, sites...); err != nil {
initErr = errors.Wrap(err, "add site dependencies") initErr = fmt.Errorf("add site dependencies: %w", err)
} }
h.Deps = sites[0].Deps h.Deps = sites[0].Deps
@ -485,7 +487,7 @@ func (l configLoader) applyDeps(cfg deps.DepsCfg, sites ...*Site) error {
siteConfig, err := l.loadSiteConfig(s.language) siteConfig, err := l.loadSiteConfig(s.language)
if err != nil { if err != nil {
return errors.Wrap(err, "load site config") return fmt.Errorf("load site config: %w", err)
} }
s.siteConfigConfig = siteConfig s.siteConfigConfig = siteConfig
@ -516,17 +518,17 @@ func (l configLoader) applyDeps(cfg deps.DepsCfg, sites ...*Site) error {
var err error var err error
d, err = deps.New(cfg) d, err = deps.New(cfg)
if err != nil { if err != nil {
return errors.Wrap(err, "create deps") return fmt.Errorf("create deps: %w", err)
} }
d.OutputFormatsConfig = s.outputFormatsConfig d.OutputFormatsConfig = s.outputFormatsConfig
if err := onCreated(d); err != nil { if err := onCreated(d); err != nil {
return errors.Wrap(err, "on created") return fmt.Errorf("on created: %w", err)
} }
if err = d.LoadResources(); err != nil { if err = d.LoadResources(); err != nil {
return errors.Wrap(err, "load resources") return fmt.Errorf("load resources: %w", err)
} }
} else { } else {
@ -548,7 +550,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
} }
sites, err := createSitesFromConfig(cfg) sites, err := createSitesFromConfig(cfg)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "from config") return nil, fmt.Errorf("from config: %w", err)
} }
return newHugoSites(cfg, sites...) return newHugoSites(cfg, sites...)
} }
@ -882,7 +884,7 @@ func (h *HugoSites) handleDataFile(r source.File) error {
f, err := r.FileInfo().Meta().Open() f, err := r.FileInfo().Meta().Open()
if err != nil { if err != nil {
return errors.Wrapf(err, "data: failed to open %q:", r.LogicalName()) return fmt.Errorf("data: failed to open %q: %w", r.LogicalName(), err)
} }
defer f.Close() defer f.Close()
@ -960,23 +962,16 @@ func (h *HugoSites) errWithFileContext(err error, f source.File) error {
if !ok { if !ok {
return err return err
} }
realFilename := fim.Meta().Filename realFilename := fim.Meta().Filename
err, _ = herrors.WithFileContextForFile( return herrors.NewFileErrorFromFile(err, realFilename, realFilename, h.SourceSpec.Fs.Source, herrors.SimpleLineMatcher)
err,
realFilename,
realFilename,
h.SourceSpec.Fs.Source,
herrors.SimpleLineMatcher)
return err
} }
func (h *HugoSites) readData(f source.File) (any, error) { func (h *HugoSites) readData(f source.File) (any, error) {
file, err := f.FileInfo().Meta().Open() file, err := f.FileInfo().Meta().Open()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "readData: failed to open data file") return nil, fmt.Errorf("readData: failed to open data file: %w", err)
} }
defer file.Close() defer file.Close()
content := helpers.ReaderToBytes(file) content := helpers.ReaderToBytes(file)

View file

@ -35,7 +35,7 @@ import (
"github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/output"
"github.com/pkg/errors" "errors"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
@ -50,7 +50,7 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
if !config.NoBuildLock { if !config.NoBuildLock {
unlock, err := h.BaseFs.LockBuild() unlock, err := h.BaseFs.LockBuild()
if err != nil { if err != nil {
return errors.Wrap(err, "failed to acquire a build lock") return fmt.Errorf("failed to acquire a build lock: %w", err)
} }
defer unlock() defer unlock()
} }
@ -99,11 +99,11 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
if len(events) > 0 { if len(events) > 0 {
// Rebuild // Rebuild
if err := h.initRebuild(conf); err != nil { if err := h.initRebuild(conf); err != nil {
return errors.Wrap(err, "initRebuild") return fmt.Errorf("initRebuild: %w", err)
} }
} else { } else {
if err := h.initSites(conf); err != nil { if err := h.initSites(conf); err != nil {
return errors.Wrap(err, "initSites") return fmt.Errorf("initSites: %w", err)
} }
} }
@ -117,7 +117,7 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
} }
trace.WithRegion(ctx, "process", f) trace.WithRegion(ctx, "process", f)
if err != nil { if err != nil {
return errors.Wrap(err, "process") return fmt.Errorf("process: %w", err)
} }
f = func() { f = func() {

View file

@ -2,6 +2,7 @@ package hugolib
import ( import (
"fmt" "fmt"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"testing" "testing"
@ -17,14 +18,15 @@ type testSiteBuildErrorAsserter struct {
c *qt.C c *qt.C
} }
func (t testSiteBuildErrorAsserter) getFileError(err error) *herrors.ErrorWithFileContext { func (t testSiteBuildErrorAsserter) getFileError(err error) herrors.FileError {
t.c.Assert(err, qt.Not(qt.IsNil), qt.Commentf(t.name)) t.c.Assert(err, qt.Not(qt.IsNil), qt.Commentf(t.name))
ferr := herrors.UnwrapErrorWithFileContext(err) fe := herrors.UnwrapFileError(err)
t.c.Assert(ferr, qt.Not(qt.IsNil)) t.c.Assert(fe, qt.Not(qt.IsNil))
return ferr return fe
} }
func (t testSiteBuildErrorAsserter) assertLineNumber(lineNumber int, err error) { func (t testSiteBuildErrorAsserter) assertLineNumber(lineNumber int, err error) {
t.c.Helper()
fe := t.getFileError(err) fe := t.getFileError(err)
t.c.Assert(fe.Position().LineNumber, qt.Equals, lineNumber, qt.Commentf(err.Error())) t.c.Assert(fe.Position().LineNumber, qt.Equals, lineNumber, qt.Commentf(err.Error()))
} }
@ -87,7 +89,6 @@ func TestSiteBuildErrors(t *testing.T) {
fe := a.getFileError(err) fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5) a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 1) a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 1)
a.c.Assert(fe.ChromaLexer, qt.Equals, "go-html-template")
a.assertErrorMessage("\"layouts/foo/single.html:5:1\": parse failed: template: foo/single.html:5: unexpected \"}\" in operand", fe.Error()) a.assertErrorMessage("\"layouts/foo/single.html:5:1\": parse failed: template: foo/single.html:5: unexpected \"}\" in operand", fe.Error())
}, },
}, },
@ -101,7 +102,6 @@ func TestSiteBuildErrors(t *testing.T) {
fe := a.getFileError(err) fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5) a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 14) a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 14)
a.c.Assert(fe.ChromaLexer, qt.Equals, "go-html-template")
a.assertErrorMessage("\"layouts/_default/single.html:5:14\": execute of template failed", fe.Error()) a.assertErrorMessage("\"layouts/_default/single.html:5:14\": execute of template failed", fe.Error())
}, },
}, },
@ -115,7 +115,6 @@ func TestSiteBuildErrors(t *testing.T) {
fe := a.getFileError(err) fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5) a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 14) a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 14)
a.c.Assert(fe.ChromaLexer, qt.Equals, "go-html-template")
a.assertErrorMessage("\"layouts/_default/single.html:5:14\": execute of template failed", fe.Error()) a.assertErrorMessage("\"layouts/_default/single.html:5:14\": execute of template failed", fe.Error())
}, },
}, },
@ -130,18 +129,17 @@ func TestSiteBuildErrors(t *testing.T) {
}, },
}, },
{ {
name: "Shortode execute failed", name: "Shortcode execute failed",
fileType: shortcode, fileType: shortcode,
fileFixer: func(content string) string { fileFixer: func(content string) string {
return strings.Replace(content, ".Title", ".Titles", 1) return strings.Replace(content, ".Title", ".Titles", 1)
}, },
assertBuildError: func(a testSiteBuildErrorAsserter, err error) { assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
fe := a.getFileError(err) fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 7)
a.c.Assert(fe.ChromaLexer, qt.Equals, "md")
// Make sure that it contains both the content file and template // Make sure that it contains both the content file and template
a.assertErrorMessage(`content/myyaml.md:7:10": failed to render shortcode "sc"`, fe.Error()) a.assertErrorMessage(`"content/myyaml.md:7:10": failed to render shortcode "sc": failed to process shortcode: "layouts/shortcodes/sc.html:4:22": execute of template failed: template: shortcodes/sc.html:4:22: executing "shortcodes/sc.html" at <.Page.Titles>: can't evaluate field Titles in type page.Page`, fe.Error())
a.assertErrorMessage(`shortcodes/sc.html:4:22: executing "shortcodes/sc.html" at <.Page.Titles>: can't evaluate`, fe.Error()) a.c.Assert(fe.Position().LineNumber, qt.Equals, 7)
}, },
}, },
{ {
@ -154,7 +152,6 @@ func TestSiteBuildErrors(t *testing.T) {
fe := a.getFileError(err) fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 7) a.c.Assert(fe.Position().LineNumber, qt.Equals, 7)
a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 10) a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 10)
a.c.Assert(fe.ChromaLexer, qt.Equals, "md")
a.assertErrorMessage(`"content/myyaml.md:7:10": failed to extract shortcode: template for shortcode "nono" not found`, fe.Error()) a.assertErrorMessage(`"content/myyaml.md:7:10": failed to extract shortcode: template for shortcode "nono" not found`, fe.Error())
}, },
}, },
@ -162,10 +159,14 @@ func TestSiteBuildErrors(t *testing.T) {
name: "Invalid YAML front matter", name: "Invalid YAML front matter",
fileType: yamlcontent, fileType: yamlcontent,
fileFixer: func(content string) string { fileFixer: func(content string) string {
return strings.Replace(content, "title:", "title: %foo", 1) return `---
title: "My YAML Content"
foo bar
---
`
}, },
assertBuildError: func(a testSiteBuildErrorAsserter, err error) { assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
a.assertLineNumber(2, err) a.assertLineNumber(3, err)
}, },
}, },
{ {
@ -177,7 +178,6 @@ func TestSiteBuildErrors(t *testing.T) {
assertBuildError: func(a testSiteBuildErrorAsserter, err error) { assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
fe := a.getFileError(err) fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 6) a.c.Assert(fe.Position().LineNumber, qt.Equals, 6)
a.c.Assert(fe.ErrorContext.ChromaLexer, qt.Equals, "toml")
}, },
}, },
{ {
@ -188,9 +188,7 @@ func TestSiteBuildErrors(t *testing.T) {
}, },
assertBuildError: func(a testSiteBuildErrorAsserter, err error) { assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
fe := a.getFileError(err) fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 3) a.c.Assert(fe.Position().LineNumber, qt.Equals, 3)
a.c.Assert(fe.ErrorContext.ChromaLexer, qt.Equals, "json")
}, },
}, },
{ {
@ -211,6 +209,9 @@ func TestSiteBuildErrors(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
if test.name != "Invalid JSON front matter" {
continue
}
test := test test := test
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
t.Parallel() t.Parallel()
@ -311,6 +312,77 @@ Some content.
} }
}) })
} }
}
// Issue 9852
func TestErrorMinify(t *testing.T) {
t.Parallel()
files := `
-- config.toml --
minify = true
-- layouts/index.html --
<body>
<script>=;</script>
</body>
`
b, err := NewIntegrationTestBuilder(
IntegrationTestConfig{
T: t,
TxtarString: files,
},
).BuildE()
fe := herrors.UnwrapFileError(err)
b.Assert(fe, qt.IsNotNil)
b.Assert(fe.Position().LineNumber, qt.Equals, 2)
b.Assert(fe.Position().ColumnNumber, qt.Equals, 9)
b.Assert(fe.Error(), qt.Contains, "unexpected = in expression on line 2 and column 9")
b.Assert(filepath.ToSlash(fe.Position().Filename), qt.Contains, "hugo-transform-error")
b.Assert(os.Remove(fe.Position().Filename), qt.IsNil)
}
func TestErrorNested(t *testing.T) {
t.Parallel()
files := `
-- config.toml --
-- layouts/index.html --
line 1
12{{ partial "foo.html" . }}
line 4
line 5
-- layouts/partials/foo.html --
line 1
line 2
123{{ .ThisDoesNotExist }}
line 4
`
b, err := NewIntegrationTestBuilder(
IntegrationTestConfig{
T: t,
TxtarString: files,
},
).BuildE()
b.Assert(err, qt.IsNotNil)
errors := herrors.UnwrapFileErrorsWithErrorContext(err)
b.Assert(errors, qt.HasLen, 2)
fmt.Println(errors[0])
b.Assert(errors[0].Position().LineNumber, qt.Equals, 2)
b.Assert(errors[0].Position().ColumnNumber, qt.Equals, 5)
b.Assert(errors[0].Error(), qt.Contains, filepath.FromSlash(`"/layouts/index.html:2:5": execute of template failed`))
b.Assert(errors[0].ErrorContext().Lines, qt.DeepEquals, []string{"line 1", "12{{ partial \"foo.html\" . }}", "line 4", "line 5"})
b.Assert(errors[1].Position().LineNumber, qt.Equals, 3)
b.Assert(errors[1].Position().ColumnNumber, qt.Equals, 6)
b.Assert(errors[1].ErrorContext().Lines, qt.DeepEquals, []string{"line 1", "line 2", "123{{ .ThisDoesNotExist }}", "line 4"})
} }
// https://github.com/gohugoio/hugo/issues/5375 // https://github.com/gohugoio/hugo/issues/5375

View file

@ -169,8 +169,7 @@ func (s *IntegrationTestBuilder) destinationExists(filename string) bool {
} }
func (s *IntegrationTestBuilder) AssertIsFileError(err error) { func (s *IntegrationTestBuilder) AssertIsFileError(err error) {
var ferr *herrors.ErrorWithFileContext s.Assert(err, qt.ErrorAs, new(herrors.FileError))
s.Assert(err, qt.ErrorAs, &ferr)
} }
func (s *IntegrationTestBuilder) AssertRenderCountContent(count int) { func (s *IntegrationTestBuilder) AssertRenderCountContent(count int) {

View file

@ -39,8 +39,9 @@ import (
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/parser/metadecoders"
"errors"
"github.com/gohugoio/hugo/parser/pageparser" "github.com/gohugoio/hugo/parser/pageparser"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/output"
@ -482,7 +483,7 @@ func (p *pageState) renderResources() (err error) {
src, ok := r.(resource.Source) src, ok := r.(resource.Source)
if !ok { if !ok {
err = errors.Errorf("Resource %T does not support resource.Source", src) err = fmt.Errorf("Resource %T does not support resource.Source", src)
return return
} }
@ -560,23 +561,37 @@ func (p *pageState) addDependency(dep identity.Provider) {
// wrapError adds some more context to the given error if possible/needed // wrapError adds some more context to the given error if possible/needed
func (p *pageState) wrapError(err error) error { func (p *pageState) wrapError(err error) error {
if _, ok := err.(*herrors.ErrorWithFileContext); ok { if err == nil {
// Preserve the first file context. panic("wrapError with nil")
return err
}
var filename string
if !p.File().IsZero() {
filename = p.File().Filename()
} }
err, _ = herrors.WithFileContextForFile( if p.File().IsZero() {
err, // No more details to add.
filename, return fmt.Errorf("%q: %w", p.Pathc(), err)
filename, }
p.s.SourceSpec.Fs.Source,
herrors.SimpleLineMatcher)
filename := p.File().Filename()
if ferr := herrors.UnwrapFileError(err); ferr != nil {
errfilename := ferr.Position().Filename
if ferr.ErrorContext() != nil || errfilename == "" || !(errfilename == pageFileErrorName || filepath.IsAbs(errfilename)) {
return err return err
}
if filepath.IsAbs(errfilename) {
filename = errfilename
}
f, ferr2 := p.s.SourceSpec.Fs.Source.Open(filename)
if ferr2 != nil {
return err
}
defer f.Close()
pos := ferr.Position()
pos.Filename = filename
return ferr.UpdatePosition(pos).UpdateContent(f, herrors.SimpleLineMatcher)
}
return herrors.NewFileErrorFromFile(err, filename, filename, p.s.SourceSpec.Fs.Source, herrors.SimpleLineMatcher)
} }
func (p *pageState) getContentConverter() converter.Converter { func (p *pageState) getContentConverter() converter.Converter {
@ -606,6 +621,9 @@ func (p *pageState) mapContent(bucket *pagesMapBucket, meta *pageMeta) error {
iter := p.source.parsed.Iterator() iter := p.source.parsed.Iterator()
fail := func(err error, i pageparser.Item) error { fail := func(err error, i pageparser.Item) error {
if fe, ok := err.(herrors.FileError); ok {
return fe
}
return p.parseError(err, iter.Input(), i.Pos) return p.parseError(err, iter.Input(), i.Pos)
} }
@ -626,7 +644,17 @@ Loop:
m, err := metadecoders.Default.UnmarshalToMap(it.Val, f) m, err := metadecoders.Default.UnmarshalToMap(it.Val, f)
if err != nil { if err != nil {
if fe, ok := err.(herrors.FileError); ok { if fe, ok := err.(herrors.FileError); ok {
return herrors.ToFileErrorWithOffset(fe, iter.LineNumber()-1) // Offset the starting position of front matter.
pos := fe.Position()
offset := iter.LineNumber() - 1
if f == metadecoders.YAML {
offset -= 1
}
pos.LineNumber += offset
fe.UpdatePosition(pos)
return fe
} else { } else {
return err return err
} }
@ -682,7 +710,7 @@ Loop:
currShortcode, err := s.extractShortcode(ordinal, 0, iter) currShortcode, err := s.extractShortcode(ordinal, 0, iter)
if err != nil { if err != nil {
return fail(errors.Wrap(err, "failed to extract shortcode"), it) return fail(err, it)
} }
currShortcode.pos = it.Pos currShortcode.pos = it.Pos
@ -715,7 +743,7 @@ Loop:
case it.IsEOF(): case it.IsEOF():
break Loop break Loop
case it.IsError(): case it.IsError():
err := fail(errors.WithStack(errors.New(it.ValStr())), it) err := fail(errors.New(it.ValStr()), it)
currShortcode.err = err currShortcode.err = err
return err return err
@ -738,17 +766,17 @@ Loop:
} }
func (p *pageState) errorf(err error, format string, a ...any) error { func (p *pageState) errorf(err error, format string, a ...any) error {
if herrors.UnwrapErrorWithFileContext(err) != nil { if herrors.UnwrapFileError(err) != nil {
// More isn't always better. // More isn't always better.
return err return err
} }
args := append([]any{p.Language().Lang, p.pathOrTitle()}, a...) args := append([]any{p.Language().Lang, p.pathOrTitle()}, a...)
format = "[%s] page %q: " + format args = append(args, err)
format = "[%s] page %q: " + format + ": %w"
if err == nil { if err == nil {
errors.Errorf(format, args...)
return fmt.Errorf(format, args...) return fmt.Errorf(format, args...)
} }
return errors.Wrapf(err, format, args...) return fmt.Errorf(format, args...)
} }
func (p *pageState) outputFormat() (f output.Format) { func (p *pageState) outputFormat() (f output.Format) {
@ -759,12 +787,8 @@ func (p *pageState) outputFormat() (f output.Format) {
} }
func (p *pageState) parseError(err error, input []byte, offset int) error { func (p *pageState) parseError(err error, input []byte, offset int) error {
if herrors.UnwrapFileError(err) != nil {
// Use the most specific location.
return err
}
pos := p.posFromInput(input, offset) pos := p.posFromInput(input, offset)
return herrors.NewFileError("md", -1, pos.LineNumber, pos.ColumnNumber, err) return herrors.NewFileError("page.md", err).UpdatePosition(pos)
} }
func (p *pageState) pathOrTitle() string { func (p *pageState) pathOrTitle() string {

View file

@ -34,7 +34,6 @@ import (
"github.com/gohugoio/hugo/related" "github.com/gohugoio/hugo/related"
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
@ -765,7 +764,7 @@ func (p *pageMeta) newContentConverter(ps *pageState, markup string, renderingCo
} }
cp := p.s.ContentSpec.Converters.Get(markup) cp := p.s.ContentSpec.Converters.Get(markup)
if cp == nil { if cp == nil {
return converter.NopConverter, errors.Errorf("no content renderer found for markup %q", p.markup) return converter.NopConverter, fmt.Errorf("no content renderer found for markup %q", p.markup)
} }
var id string var id string

View file

@ -23,11 +23,12 @@ import (
"sync" "sync"
"unicode/utf8" "unicode/utf8"
"errors"
"github.com/gohugoio/hugo/common/text" "github.com/gohugoio/hugo/common/text"
"github.com/gohugoio/hugo/common/types/hstring" "github.com/gohugoio/hugo/common/types/hstring"
"github.com/gohugoio/hugo/identity" "github.com/gohugoio/hugo/identity"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/gohugoio/hugo/markup/converter/hooks" "github.com/gohugoio/hugo/markup/converter/hooks"
@ -348,7 +349,7 @@ func (p *pageContentOutput) RenderString(args ...any) (template.HTML, error) {
} }
if err := mapstructure.WeakDecode(m, &opts); err != nil { if err := mapstructure.WeakDecode(m, &opts); err != nil {
return "", errors.WithMessage(err, "failed to decode options") return "", fmt.Errorf("failed to decode options: %w", err)
} }
} }
@ -416,7 +417,7 @@ func (p *pageContentOutput) Render(layout ...string) (template.HTML, error) {
// Make sure to send the *pageState and not the *pageContentOutput to the template. // Make sure to send the *pageState and not the *pageContentOutput to the template.
res, err := executeToString(p.p.s.Tmpl(), templ, p.p) res, err := executeToString(p.p.s.Tmpl(), templ, p.p)
if err != nil { if err != nil {
return "", p.p.wrapError(errors.Wrapf(err, "failed to execute template %q v", layout)) return "", p.p.wrapError(fmt.Errorf("failed to execute template %q v: %w", layout, err))
} }
return template.HTML(res), nil return template.HTML(res), nil
} }

View file

@ -19,7 +19,6 @@ import (
"github.com/gohugoio/hugo/common/text" "github.com/gohugoio/hugo/common/text"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
) )
func newPageRef(p *pageState) pageRef { func newPageRef(p *pageState) pageRef {
@ -77,7 +76,7 @@ func (p pageRef) decodeRefArgs(args map[string]any) (refArgs, *Site, error) {
func (p pageRef) ref(argsm map[string]any, source any) (string, error) { func (p pageRef) ref(argsm map[string]any, source any) (string, error) {
args, s, err := p.decodeRefArgs(argsm) args, s, err := p.decodeRefArgs(argsm)
if err != nil { if err != nil {
return "", errors.Wrap(err, "invalid arguments to Ref") return "", fmt.Errorf("invalid arguments to Ref: %w", err)
} }
if s == nil { if s == nil {
@ -94,7 +93,7 @@ func (p pageRef) ref(argsm map[string]any, source any) (string, error) {
func (p pageRef) relRef(argsm map[string]any, source any) (string, error) { func (p pageRef) relRef(argsm map[string]any, source any) (string, error) {
args, s, err := p.decodeRefArgs(argsm) args, s, err := p.decodeRefArgs(argsm)
if err != nil { if err != nil {
return "", errors.Wrap(err, "invalid arguments to Ref") return "", fmt.Errorf("invalid arguments to Ref: %w", err)
} }
if s == nil { if s == nil {

View file

@ -14,7 +14,7 @@
package hugolib package hugolib
import ( import (
"github.com/pkg/errors" "fmt"
"github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/page"
) )
@ -36,7 +36,7 @@ func unwrapPage(in any) (page.Page, error) {
case nil: case nil:
return nil, nil return nil, nil
default: default:
return nil, errors.Errorf("unwrapPage: %T not supported", in) return nil, fmt.Errorf("unwrapPage: %T not supported", in)
} }
} }

View file

@ -22,7 +22,6 @@ import (
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
@ -156,7 +155,7 @@ func (p *sitePagesProcessor) copyFile(fim hugofs.FileMetaInfo) error {
meta := fim.Meta() meta := fim.Meta()
f, err := meta.Open() f, err := meta.Open()
if err != nil { if err != nil {
return errors.Wrap(err, "copyFile: failed to open") return fmt.Errorf("copyFile: failed to open: %w", err)
} }
s := p.m.s s := p.m.s

View file

@ -23,7 +23,6 @@ import (
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/modules" "github.com/gohugoio/hugo/modules"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
) )
@ -83,7 +82,7 @@ func New(fs *hugofs.Fs, cfg config.Provider) (*Paths, error) {
baseURLstr := cfg.GetString("baseURL") baseURLstr := cfg.GetString("baseURL")
baseURL, err := newBaseURLFromString(baseURLstr) baseURL, err := newBaseURLFromString(baseURLstr)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "Failed to create baseURL from %q:", baseURLstr) return nil, fmt.Errorf("Failed to create baseURL from %q:: %w", baseURLstr, err)
} }
contentDir := filepath.Clean(cfg.GetString("contentDir")) contentDir := filepath.Clean(cfg.GetString("contentDir"))

View file

@ -27,8 +27,9 @@ import (
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"errors"
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/parser/pageparser" "github.com/gohugoio/hugo/parser/pageparser"
"github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/page"
@ -269,6 +270,7 @@ const (
innerNewlineRegexp = "\n" innerNewlineRegexp = "\n"
innerCleanupRegexp = `\A<p>(.*)</p>\n\z` innerCleanupRegexp = `\A<p>(.*)</p>\n\z`
innerCleanupExpand = "$1" innerCleanupExpand = "$1"
pageFileErrorName = "page.md"
) )
func renderShortcode( func renderShortcode(
@ -297,9 +299,10 @@ func renderShortcode(
var err error var err error
tmpl, err = s.TextTmpl().Parse(templName, templStr) tmpl, err = s.TextTmpl().Parse(templName, templStr)
if err != nil { if err != nil {
fe := herrors.ToFileError("html", err) fe := herrors.NewFileError(pageFileErrorName, err)
l1, l2 := p.posOffset(sc.pos).LineNumber, fe.Position().LineNumber pos := fe.Position()
fe = herrors.ToFileErrorWithLineNumber(fe, l1+l2-1) pos.LineNumber += p.posOffset(sc.pos).LineNumber
fe = fe.UpdatePosition(pos)
return "", false, p.wrapError(fe) return "", false, p.wrapError(fe)
} }
@ -308,7 +311,7 @@ func renderShortcode(
var found bool var found bool
tmpl, found = s.TextTmpl().Lookup(templName) tmpl, found = s.TextTmpl().Lookup(templName)
if !found { if !found {
return "", false, errors.Errorf("no earlier definition of shortcode %q found", sc.name) return "", false, fmt.Errorf("no earlier definition of shortcode %q found", sc.name)
} }
} }
} else { } else {
@ -389,9 +392,10 @@ func renderShortcode(
result, err := renderShortcodeWithPage(s.Tmpl(), tmpl, data) result, err := renderShortcodeWithPage(s.Tmpl(), tmpl, data)
if err != nil && sc.isInline { if err != nil && sc.isInline {
fe := herrors.ToFileError("html", err) fe := herrors.NewFileError("shortcode.md", err)
l1, l2 := p.posFromPage(sc.pos).LineNumber, fe.Position().LineNumber pos := fe.Position()
fe = herrors.ToFileErrorWithLineNumber(fe, l1+l2-1) pos.LineNumber += p.posOffset(sc.pos).LineNumber
fe = fe.UpdatePosition(pos)
return "", false, fe return "", false, fe
} }
@ -415,7 +419,7 @@ func (s *shortcodeHandler) renderShortcodesForPage(p *pageState, f output.Format
for _, v := range s.shortcodes { for _, v := range s.shortcodes {
s, more, err := renderShortcode(0, s.s, tplVariants, v, nil, p) s, more, err := renderShortcode(0, s.s, tplVariants, v, nil, p)
if err != nil { if err != nil {
err = p.parseError(errors.Wrapf(err, "failed to render shortcode %q", v.name), p.source.parsed.Input(), v.pos) err = p.parseError(fmt.Errorf("failed to render shortcode %q: %w", v.name, err), p.source.parsed.Input(), v.pos)
return nil, false, err return nil, false, err
} }
hasVariants = hasVariants || more hasVariants = hasVariants || more
@ -447,9 +451,10 @@ func (s *shortcodeHandler) extractShortcode(ordinal, level int, pt *pageparser.I
cnt := 0 cnt := 0
nestedOrdinal := 0 nestedOrdinal := 0
nextLevel := level + 1 nextLevel := level + 1
const errorPrefix = "failed to extract shortcode"
fail := func(err error, i pageparser.Item) error { fail := func(err error, i pageparser.Item) error {
return s.parseError(err, pt.Input(), i.Pos) return s.parseError(fmt.Errorf("%s: %w", errorPrefix, err), pt.Input(), i.Pos)
} }
Loop: Loop:
@ -508,7 +513,7 @@ Loop:
// return that error, more specific // return that error, more specific
continue continue
} }
return sc, fail(errors.Errorf("shortcode %q has no .Inner, yet a closing tag was provided", next.Val), next) return sc, fail(fmt.Errorf("shortcode %q has no .Inner, yet a closing tag was provided", next.Val), next)
} }
} }
if next.IsRightShortcodeDelim() { if next.IsRightShortcodeDelim() {
@ -538,7 +543,7 @@ Loop:
// Used to check if the template expects inner content. // Used to check if the template expects inner content.
templs := s.s.Tmpl().LookupVariants(sc.name) templs := s.s.Tmpl().LookupVariants(sc.name)
if templs == nil { if templs == nil {
return nil, errors.Errorf("template for shortcode %q not found", sc.name) return nil, fmt.Errorf("%s: template for shortcode %q not found", errorPrefix, sc.name)
} }
sc.info = templs[0].(tpl.Info) sc.info = templs[0].(tpl.Info)
@ -639,7 +644,7 @@ func renderShortcodeWithPage(h tpl.TemplateHandler, tmpl tpl.Template, data *Sho
err := h.Execute(tmpl, buffer, data) err := h.Execute(tmpl, buffer, data)
if err != nil { if err != nil {
return "", errors.Wrap(err, "failed to process shortcode") return "", fmt.Errorf("failed to process shortcode: %w", err)
} }
return buffer.String(), nil return buffer.String(), nil
} }

View file

@ -1340,7 +1340,7 @@ func TestShortcodeNoInner(t *testing.T) {
b := newTestSitesBuilder(t) b := newTestSitesBuilder(t)
b.WithContent("page.md", `--- b.WithContent("mypage.md", `---
title: "No Inner!" title: "No Inner!"
--- ---
{{< noinner >}}{{< /noinner >}} {{< noinner >}}{{< /noinner >}}
@ -1350,7 +1350,7 @@ title: "No Inner!"
"layouts/shortcodes/noinner.html", `No inner here.`) "layouts/shortcodes/noinner.html", `No inner here.`)
err := b.BuildE(BuildCfg{}) err := b.BuildE(BuildCfg{})
b.Assert(err.Error(), qt.Contains, `failed to extract shortcode: shortcode "noinner" has no .Inner, yet a closing tag was provided`) b.Assert(err.Error(), qt.Contains, filepath.FromSlash(`"content/mypage.md:4:21": failed to extract shortcode: shortcode "noinner" has no .Inner, yet a closing tag was provided`))
} }
func TestShortcodeStableOutputFormatTemplates(t *testing.T) { func TestShortcodeStableOutputFormatTemplates(t *testing.T) {

View file

@ -59,8 +59,6 @@ import (
"github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/publisher" "github.com/gohugoio/hugo/publisher"
"github.com/pkg/errors"
_errors "github.com/pkg/errors"
"github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/langs"
@ -508,7 +506,7 @@ But this also means that your site configuration may not do what you expect. If
if cfg.Language.IsSet("related") { if cfg.Language.IsSet("related") {
relatedContentConfig, err = related.DecodeConfig(cfg.Language.GetParams("related")) relatedContentConfig, err = related.DecodeConfig(cfg.Language.GetParams("related"))
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to decode related config") return nil, fmt.Errorf("failed to decode related config: %w", err)
} }
} else { } else {
relatedContentConfig = related.DefaultConfig relatedContentConfig = related.DefaultConfig
@ -546,7 +544,7 @@ But this also means that your site configuration may not do what you expect. If
var err error var err error
cascade, err := page.DecodeCascade(cfg.Language.Get("cascade")) cascade, err := page.DecodeCascade(cfg.Language.Get("cascade"))
if err != nil { if err != nil {
return nil, errors.Errorf("failed to decode cascade config: %s", err) return nil, fmt.Errorf("failed to decode cascade config: %s", err)
} }
siteBucket = &pagesMapBucket{ siteBucket = &pagesMapBucket{
@ -1211,11 +1209,11 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
func (s *Site) process(config BuildCfg) (err error) { func (s *Site) process(config BuildCfg) (err error) {
if err = s.initialize(); err != nil { if err = s.initialize(); err != nil {
err = errors.Wrap(err, "initialize") err = fmt.Errorf("initialize: %w", err)
return return
} }
if err = s.readAndProcessContent(config); err != nil { if err = s.readAndProcessContent(config); err != nil {
err = errors.Wrap(err, "readAndProcessContent") err = fmt.Errorf("readAndProcessContent: %w", err)
return return
} }
return err return err
@ -1534,7 +1532,7 @@ func (s *Site) assembleMenus() {
for name, me := range p.pageMenus.menus() { for name, me := range p.pageMenus.menus() {
if _, ok := flat[twoD{name, me.KeyName()}]; ok { if _, ok := flat[twoD{name, me.KeyName()}]; ok {
err := p.wrapError(errors.Errorf("duplicate menu entry with identifier %q in menu %q", me.KeyName(), name)) err := p.wrapError(fmt.Errorf("duplicate menu entry with identifier %q in menu %q", me.KeyName(), name))
s.Log.Warnln(err) s.Log.Warnln(err)
continue continue
} }
@ -1819,7 +1817,7 @@ func (s *Site) renderForTemplate(name, outputFormat string, d any, w io.Writer,
} }
if err = s.Tmpl().Execute(templ, w, d); err != nil { if err = s.Tmpl().Execute(templ, w, d); err != nil {
return _errors.Wrapf(err, "render of %q failed", name) return fmt.Errorf("render of %q failed: %w", name, err)
} }
return return
} }

View file

@ -23,8 +23,9 @@ import (
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
"errors"
"github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/output"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/resources/page/pagemeta" "github.com/gohugoio/hugo/resources/page/pagemeta"
@ -95,7 +96,7 @@ func (s *Site) renderPages(ctx *siteRenderContext) error {
err := <-errs err := <-errs
if err != nil { if err != nil {
return errors.Wrap(err, "failed to render pages") return fmt.Errorf("failed to render pages: %w", err)
} }
return nil return nil
} }

View file

@ -28,10 +28,8 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/gohugoio/hugo/parser" "github.com/gohugoio/hugo/parser"
"github.com/pkg/errors"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
@ -471,7 +469,6 @@ func (s *sitesBuilder) writeFilePairs(folder string, files []filenameContent) *s
func (s *sitesBuilder) CreateSites() *sitesBuilder { func (s *sitesBuilder) CreateSites() *sitesBuilder {
if err := s.CreateSitesE(); err != nil { if err := s.CreateSitesE(); err != nil {
herrors.PrintStackTraceFromErr(err)
s.Fatalf("Failed to create sites: %s", err) s.Fatalf("Failed to create sites: %s", err)
} }
@ -517,7 +514,7 @@ func (s *sitesBuilder) CreateSitesE() error {
"i18n", "i18n",
} { } {
if err := os.MkdirAll(filepath.Join(s.workingDir, dir), 0777); err != nil { if err := os.MkdirAll(filepath.Join(s.workingDir, dir), 0777); err != nil {
return errors.Wrapf(err, "failed to create %q", dir) return fmt.Errorf("failed to create %q: %w", dir, err)
} }
} }
} }
@ -536,7 +533,7 @@ func (s *sitesBuilder) CreateSitesE() error {
} }
if err := s.LoadConfig(); err != nil { if err := s.LoadConfig(); err != nil {
return errors.Wrap(err, "failed to load config") return fmt.Errorf("failed to load config: %w", err)
} }
s.Fs.PublishDir = hugofs.NewCreateCountingFs(s.Fs.PublishDir) s.Fs.PublishDir = hugofs.NewCreateCountingFs(s.Fs.PublishDir)
@ -549,7 +546,7 @@ func (s *sitesBuilder) CreateSitesE() error {
sites, err := NewHugoSites(depsCfg) sites, err := NewHugoSites(depsCfg)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to create sites") return fmt.Errorf("failed to create sites: %w", err)
} }
s.H = sites s.H = sites
@ -612,7 +609,6 @@ func (s *sitesBuilder) build(cfg BuildCfg, shouldFail bool) *sitesBuilder {
} }
} }
if err != nil && !shouldFail { if err != nil && !shouldFail {
herrors.PrintStackTraceFromErr(err)
s.Fatalf("Build failed: %s", err) s.Fatalf("Build failed: %s", err)
} else if err == nil && shouldFail { } else if err == nil && shouldFail {
s.Fatalf("Expected error") s.Fatalf("Expected error")

View file

@ -23,7 +23,7 @@ import (
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
) )
@ -72,7 +72,7 @@ func LoadLanguageSettings(cfg config.Provider, oldLangs Languages) (c LanguagesC
} else { } else {
languages2, err = toSortedLanguages(cfg, languages) languages2, err = toSortedLanguages(cfg, languages)
if err != nil { if err != nil {
return c, errors.Wrap(err, "Failed to parse multilingual config") return c, fmt.Errorf("Failed to parse multilingual config: %w", err)
} }
} }

View file

@ -15,6 +15,7 @@ package i18n
import ( import (
"encoding/json" "encoding/json"
"fmt"
"strings" "strings"
"github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/paths"
@ -30,7 +31,6 @@ import (
"github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
_errors "github.com/pkg/errors"
) )
// TranslationProvider provides translation handling, i.e. loading // TranslationProvider provides translation handling, i.e. loading
@ -83,7 +83,7 @@ const artificialLangTagPrefix = "art-x-"
func addTranslationFile(bundle *i18n.Bundle, r source.File) error { func addTranslationFile(bundle *i18n.Bundle, r source.File) error {
f, err := r.FileInfo().Meta().Open() f, err := r.FileInfo().Meta().Open()
if err != nil { if err != nil {
return _errors.Wrapf(err, "failed to open translations file %q:", r.LogicalName()) return fmt.Errorf("failed to open translations file %q:: %w", r.LogicalName(), err)
} }
b := helpers.ReaderToBytes(f) b := helpers.ReaderToBytes(f)
@ -96,7 +96,7 @@ func addTranslationFile(bundle *i18n.Bundle, r source.File) error {
try := artificialLangTagPrefix + lang try := artificialLangTagPrefix + lang
_, err = language.Parse(try) _, err = language.Parse(try)
if err != nil { if err != nil {
return _errors.Errorf("%q %s.", try, err) return fmt.Errorf("%q: %s", try, err)
} }
name = artificialLangTagPrefix + name name = artificialLangTagPrefix + name
} }
@ -111,7 +111,7 @@ func addTranslationFile(bundle *i18n.Bundle, r source.File) error {
return nil return nil
} }
} }
return errWithFileContext(_errors.Wrapf(err, "failed to load translations"), r) return errWithFileContext(fmt.Errorf("failed to load translations: %w", err), r)
} }
return nil return nil
@ -138,11 +138,6 @@ func errWithFileContext(inerr error, r source.File) error {
} }
defer f.Close() defer f.Close()
err, _ = herrors.WithFileContext( return herrors.NewFileError(realFilename, inerr).UpdateContent(f, herrors.SimpleLineMatcher)
inerr,
realFilename,
f,
herrors.SimpleLineMatcher)
return err
} }

View file

@ -14,6 +14,7 @@
package langs package langs
import ( import (
"fmt"
"sort" "sort"
"strings" "strings"
"sync" "sync"
@ -22,8 +23,6 @@ import (
"golang.org/x/text/collate" "golang.org/x/text/collate"
"golang.org/x/text/language" "golang.org/x/text/language"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/htime"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
@ -311,7 +310,7 @@ func GetCollator(l *Language) *Collator {
func (l *Language) loadLocation(tzStr string) error { func (l *Language) loadLocation(tzStr string) error {
location, err := time.LoadLocation(tzStr) location, err := time.LoadLocation(tzStr)
if err != nil { if err != nil {
return errors.Wrapf(err, "invalid timeZone for language %q", l.Lang) return fmt.Errorf("invalid timeZone for language %q: %w", l.Lang, err)
} }
l.location = location l.location = location

View file

@ -19,7 +19,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/pkg/errors" "errors"
) )
// New creates a new empty Init. // New creates a new empty Init.

View file

@ -19,8 +19,9 @@
package blackfriday_config package blackfriday_config
import ( import (
"fmt"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
) )
// Default holds the default BlackFriday config. // Default holds the default BlackFriday config.
@ -64,7 +65,7 @@ type Config struct {
func UpdateConfig(b Config, m map[string]any) (Config, error) { func UpdateConfig(b Config, m map[string]any) (Config, error) {
if err := mapstructure.Decode(m, &b); err != nil { if err := mapstructure.Decode(m, &b); err != nil {
return b, errors.WithMessage(err, "failed to decode rendering config") return b, fmt.Errorf("failed to decode rendering config: %w", err)
} }
return b, nil return b, nil
} }

View file

@ -47,7 +47,8 @@ import (
"github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/hugio"
"github.com/pkg/errors" "errors"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
@ -241,7 +242,7 @@ func (c *Client) Vendor() error {
// See https://github.com/gohugoio/hugo/issues/8239 // See https://github.com/gohugoio/hugo/issues/8239
// This is an error situation. We need something to vendor. // This is an error situation. We need something to vendor.
if t.Mounts() == nil { if t.Mounts() == nil {
return errors.Errorf("cannot vendor module %q, need at least one mount", t.Path()) return fmt.Errorf("cannot vendor module %q, need at least one mount", t.Path())
} }
fmt.Fprintln(&modulesContent, "# "+t.Path()+" "+t.Version()) fmt.Fprintln(&modulesContent, "# "+t.Path()+" "+t.Version())
@ -253,22 +254,22 @@ func (c *Client) Vendor() error {
targetFilename := filepath.Join(vendorDir, t.Path(), mount.Source) targetFilename := filepath.Join(vendorDir, t.Path(), mount.Source)
fi, err := c.fs.Stat(sourceFilename) fi, err := c.fs.Stat(sourceFilename)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to vendor module") return fmt.Errorf("failed to vendor module: %w", err)
} }
if fi.IsDir() { if fi.IsDir() {
if err := hugio.CopyDir(c.fs, sourceFilename, targetFilename, nil); err != nil { if err := hugio.CopyDir(c.fs, sourceFilename, targetFilename, nil); err != nil {
return errors.Wrap(err, "failed to copy module to vendor dir") return fmt.Errorf("failed to copy module to vendor dir: %w", err)
} }
} else { } else {
targetDir := filepath.Dir(targetFilename) targetDir := filepath.Dir(targetFilename)
if err := c.fs.MkdirAll(targetDir, 0755); err != nil { if err := c.fs.MkdirAll(targetDir, 0755); err != nil {
return errors.Wrap(err, "failed to make target dir") return fmt.Errorf("failed to make target dir: %w", err)
} }
if err := hugio.CopyFile(c.fs, sourceFilename, targetFilename); err != nil { if err := hugio.CopyFile(c.fs, sourceFilename, targetFilename); err != nil {
return errors.Wrap(err, "failed to copy module file to vendor") return fmt.Errorf("failed to copy module file to vendor: %w", err)
} }
} }
} }
@ -278,7 +279,7 @@ func (c *Client) Vendor() error {
_, err := c.fs.Stat(resourcesDir) _, err := c.fs.Stat(resourcesDir)
if err == nil { if err == nil {
if err := hugio.CopyDir(c.fs, resourcesDir, filepath.Join(vendorDir, t.Path(), files.FolderResources), nil); err != nil { if err := hugio.CopyDir(c.fs, resourcesDir, filepath.Join(vendorDir, t.Path(), files.FolderResources), nil); err != nil {
return errors.Wrap(err, "failed to copy resources to vendor dir") return fmt.Errorf("failed to copy resources to vendor dir: %w", err)
} }
} }
@ -287,7 +288,7 @@ func (c *Client) Vendor() error {
_, err = c.fs.Stat(configDir) _, err = c.fs.Stat(configDir)
if err == nil { if err == nil {
if err := hugio.CopyDir(c.fs, configDir, filepath.Join(vendorDir, t.Path(), "config"), nil); err != nil { if err := hugio.CopyDir(c.fs, configDir, filepath.Join(vendorDir, t.Path(), "config"), nil); err != nil {
return errors.Wrap(err, "failed to copy config dir to vendor dir") return fmt.Errorf("failed to copy config dir to vendor dir: %w", err)
} }
} }
@ -361,7 +362,7 @@ func (c *Client) get(args ...string) error {
args = append([]string{"-d"}, args...) args = append([]string{"-d"}, args...)
} }
if err := c.runGo(context.Background(), c.logger.Out(), append([]string{"get"}, args...)...); err != nil { if err := c.runGo(context.Background(), c.logger.Out(), append([]string{"get"}, args...)...); err != nil {
errors.Wrapf(err, "failed to get %q", args) return fmt.Errorf("failed to get %q: %w", args, err)
} }
return nil return nil
} }
@ -372,7 +373,7 @@ func (c *Client) get(args ...string) error {
func (c *Client) Init(path string) error { func (c *Client) Init(path string) error {
err := c.runGo(context.Background(), c.logger.Out(), "mod", "init", path) err := c.runGo(context.Background(), c.logger.Out(), "mod", "init", path)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to init modules") return fmt.Errorf("failed to init modules: %w", err)
} }
c.GoModulesFilename = filepath.Join(c.ccfg.WorkingDir, goModFilename) c.GoModulesFilename = filepath.Join(c.ccfg.WorkingDir, goModFilename)
@ -458,7 +459,7 @@ func (c *Client) listGoMods() (goModules, error) {
out := ioutil.Discard out := ioutil.Discard
err := c.runGo(context.Background(), out, args...) err := c.runGo(context.Background(), out, args...)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to download modules") return fmt.Errorf("failed to download modules: %w", err)
} }
return nil return nil
} }
@ -477,7 +478,7 @@ func (c *Client) listGoMods() (goModules, error) {
} }
err := c.runGo(context.Background(), b, args...) err := c.runGo(context.Background(), b, args...)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to list modules") return fmt.Errorf("failed to list modules: %w", err)
} }
dec := json.NewDecoder(b) dec := json.NewDecoder(b)
@ -487,7 +488,7 @@ func (c *Client) listGoMods() (goModules, error) {
if err == io.EOF { if err == io.EOF {
break break
} }
return errors.Wrap(err, "failed to decode modules list") return fmt.Errorf("failed to decode modules list: %w", err)
} }
if err := handle(m); err != nil { if err := handle(m); err != nil {
@ -657,7 +658,7 @@ If you then run 'hugo mod graph' it should resolve itself to the most recent ver
_, ok := err.(*exec.ExitError) _, ok := err.(*exec.ExitError)
if !ok { if !ok {
return errors.Errorf("failed to execute 'go %v': %s %T", args, err, err) return fmt.Errorf("failed to execute 'go %v': %s %T", args, err, err)
} }
// Too old Go version // Too old Go version
@ -666,7 +667,7 @@ If you then run 'hugo mod graph' it should resolve itself to the most recent ver
return nil return nil
} }
return errors.Errorf("go command failed: %s", stderr) return fmt.Errorf("go command failed: %s", stderr)
} }
@ -706,7 +707,7 @@ func (c *Client) shouldVendor(path string) bool {
} }
func (c *Client) createThemeDirname(modulePath string, isProjectMod bool) (string, error) { func (c *Client) createThemeDirname(modulePath string, isProjectMod bool) (string, error) {
invalid := errors.Errorf("invalid module path %q; must be relative to themesDir when defined outside of the project", modulePath) invalid := fmt.Errorf("invalid module path %q; must be relative to themesDir when defined outside of the project", modulePath)
modulePath = filepath.Clean(modulePath) modulePath = filepath.Clean(modulePath)
if filepath.IsAbs(modulePath) { if filepath.IsAbs(modulePath) {

View file

@ -36,7 +36,7 @@ import (
"github.com/rogpeppe/go-internal/module" "github.com/rogpeppe/go-internal/module"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
"github.com/spf13/afero" "github.com/spf13/afero"
@ -48,7 +48,7 @@ const vendorModulesFilename = "modules.txt"
// IsNotExist returns whether an error means that a module could not be found. // IsNotExist returns whether an error means that a module could not be found.
func IsNotExist(err error) bool { func IsNotExist(err error) bool {
return errors.Cause(err) == ErrNotExist return errors.Is(err, os.ErrNotExist)
} }
// CreateProjectModule creates modules from the given config. // CreateProjectModule creates modules from the given config.
@ -289,7 +289,7 @@ func (c *collector) add(owner *moduleAdapter, moduleImport Import, disabled bool
return nil, nil return nil, nil
} }
if found, _ := afero.Exists(c.fs, moduleDir); !found { if found, _ := afero.Exists(c.fs, moduleDir); !found {
c.err = c.wrapModuleNotFound(errors.Errorf(`module %q not found; either add it as a Hugo Module or store it in %q.`, modulePath, c.ccfg.ThemesDir)) c.err = c.wrapModuleNotFound(fmt.Errorf(`module %q not found; either add it as a Hugo Module or store it in %q.`, modulePath, c.ccfg.ThemesDir))
return nil, nil return nil, nil
} }
} }
@ -297,7 +297,7 @@ func (c *collector) add(owner *moduleAdapter, moduleImport Import, disabled bool
} }
if found, _ := afero.Exists(c.fs, moduleDir); !found { if found, _ := afero.Exists(c.fs, moduleDir); !found {
c.err = c.wrapModuleNotFound(errors.Errorf("%q not found", moduleDir)) c.err = c.wrapModuleNotFound(fmt.Errorf("%q not found", moduleDir))
return nil, nil return nil, nil
} }
@ -557,7 +557,7 @@ func (c *collector) collectModulesTXT(owner Module) error {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
parts := strings.Fields(line) parts := strings.Fields(line)
if len(parts) != 2 { if len(parts) != 2 {
return errors.Errorf("invalid modules list: %q", filename) return fmt.Errorf("invalid modules list: %q", filename)
} }
path := parts[0] path := parts[0]
@ -662,7 +662,7 @@ func (c *collector) normalizeMounts(owner *moduleAdapter, mounts []Mount) ([]Mou
targetBase = mnt.Target[0:idxPathSep] targetBase = mnt.Target[0:idxPathSep]
} }
if !files.IsComponentFolder(targetBase) { if !files.IsComponentFolder(targetBase) {
return nil, errors.Errorf("%s: mount target must be one of: %v", errMsg, files.ComponentFolders) return nil, fmt.Errorf("%s: mount target must be one of: %v", errMsg, files.ComponentFolders)
} }
out = append(out, mnt) out = append(out, mnt)
@ -672,7 +672,7 @@ func (c *collector) normalizeMounts(owner *moduleAdapter, mounts []Mount) ([]Mou
} }
func (c *collector) wrapModuleNotFound(err error) error { func (c *collector) wrapModuleNotFound(err error) error {
err = errors.Wrap(ErrNotExist, err.Error()) err = fmt.Errorf(err.Error()+": %w", ErrNotExist)
if c.GoModulesFilename == "" { if c.GoModulesFilename == "" {
return err return err
} }
@ -681,9 +681,9 @@ func (c *collector) wrapModuleNotFound(err error) error {
switch c.goBinaryStatus { switch c.goBinaryStatus {
case goBinaryStatusNotFound: case goBinaryStatusNotFound:
return errors.Wrap(err, baseMsg+" you need to install Go to use it. See https://golang.org/dl/.") return fmt.Errorf(baseMsg+" you need to install Go to use it. See https://golang.org/dl/ : %q", err)
case goBinaryStatusTooOld: case goBinaryStatusTooOld:
return errors.Wrap(err, baseMsg+" you need to a newer version of Go to use it. See https://golang.org/dl/.") return fmt.Errorf(baseMsg+" you need to a newer version of Go to use it. See https://golang.org/dl/ : %w", err)
} }
return err return err

View file

@ -18,8 +18,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
@ -226,7 +224,7 @@ func decodeConfig(cfg config.Provider, pathReplacements map[string]string) (Conf
for _, repl := range c.Replacements { for _, repl := range c.Replacements {
parts := strings.Split(repl, "->") parts := strings.Split(repl, "->")
if len(parts) != 2 { if len(parts) != 2 {
return c, errors.Errorf(`invalid module.replacements: %q; configure replacement pairs on the form "oldpath->newpath" `, repl) return c, fmt.Errorf(`invalid module.replacements: %q; configure replacement pairs on the form "oldpath->newpath" `, repl)
} }
c.replacementsMap[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) c.replacementsMap[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])

View file

@ -24,8 +24,6 @@ import (
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/spf13/afero" "github.com/spf13/afero"
@ -57,7 +55,7 @@ func Pack(fs afero.Fs, fis []hugofs.FileMetaInfo) error {
if err == nil { if err == nil {
// Preserve the original in package.hugo.json. // Preserve the original in package.hugo.json.
if err = hugio.CopyFile(fs, packageJSONName, files.FilenamePackageHugoJSON); err != nil { if err = hugio.CopyFile(fs, packageJSONName, files.FilenamePackageHugoJSON); err != nil {
return errors.Wrap(err, "npm pack: failed to copy package file") return fmt.Errorf("npm pack: failed to copy package file: %w", err)
} }
} else { } else {
// Create one. // Create one.
@ -83,7 +81,7 @@ func Pack(fs afero.Fs, fis []hugofs.FileMetaInfo) error {
masterFilename := meta.Filename masterFilename := meta.Filename
f, err := meta.Open() f, err := meta.Open()
if err != nil { if err != nil {
return errors.Wrap(err, "npm pack: failed to open package file") return fmt.Errorf("npm pack: failed to open package file: %w", err)
} }
b = newPackageBuilder(meta.Module, f) b = newPackageBuilder(meta.Module, f)
f.Close() f.Close()
@ -106,14 +104,14 @@ func Pack(fs afero.Fs, fis []hugofs.FileMetaInfo) error {
f, err := meta.Open() f, err := meta.Open()
if err != nil { if err != nil {
return errors.Wrap(err, "npm pack: failed to open package file") return fmt.Errorf("npm pack: failed to open package file: %w", err)
} }
b.Add(meta.Module, f) b.Add(meta.Module, f)
f.Close() f.Close()
} }
if b.Err() != nil { if b.Err() != nil {
return errors.Wrap(b.Err(), "npm pack: failed to build") return fmt.Errorf("npm pack: failed to build: %w", b.Err())
} }
// Replace the dependencies in the original template with the merged set. // Replace the dependencies in the original template with the merged set.
@ -136,11 +134,11 @@ func Pack(fs afero.Fs, fis []hugofs.FileMetaInfo) error {
encoder.SetEscapeHTML(false) encoder.SetEscapeHTML(false)
encoder.SetIndent("", strings.Repeat(" ", 2)) encoder.SetIndent("", strings.Repeat(" ", 2))
if err := encoder.Encode(b.originalPackageJSON); err != nil { if err := encoder.Encode(b.originalPackageJSON); err != nil {
return errors.Wrap(err, "npm pack: failed to marshal JSON") return fmt.Errorf("npm pack: failed to marshal JSON: %w", err)
} }
if err := afero.WriteFile(fs, packageJSONName, packageJSONData.Bytes(), 0666); err != nil { if err := afero.WriteFile(fs, packageJSONName, packageJSONData.Bytes(), 0666); err != nil {
return errors.Wrap(err, "npm pack: failed to write package.json") return fmt.Errorf("npm pack: failed to write package.json: %w", err)
} }
return nil return nil

View file

@ -19,8 +19,6 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/compare" "github.com/gohugoio/hugo/compare"
@ -190,7 +188,7 @@ func (m *MenuEntry) MarshallMap(ime map[string]any) error {
} }
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to marshal menu entry %q", m.KeyName()) return fmt.Errorf("failed to marshal menu entry %q: %w", m.KeyName(), err)
} }
return nil return nil

View file

@ -14,10 +14,11 @@
package navigation package navigation
import ( import (
"fmt"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/types"
"github.com/pkg/errors"
"github.com/spf13/cast" "github.com/spf13/cast"
) )
@ -76,7 +77,7 @@ func PageMenusFromPage(p Page) (PageMenus, error) {
} }
var wrapErr = func(err error) error { var wrapErr = func(err error) error {
return errors.Wrapf(err, "unable to process menus for page %q", p.Path()) return fmt.Errorf("unable to process menus for page %q: %w", p.Path(), err)
} }
// Could be a structured menu entry // Could be a structured menu entry

View file

@ -20,8 +20,6 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/pkg/errors"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
@ -364,7 +362,7 @@ func decode(mediaTypes media.Types, input any, output *Format) error {
} }
dataVal.SetMapIndex(key, reflect.ValueOf(mediaType)) dataVal.SetMapIndex(key, reflect.ValueOf(mediaType))
default: default:
return nil, errors.Errorf("invalid output format configuration; wrong type for media type, expected string (e.g. text/html), got %T", vvi) return nil, fmt.Errorf("invalid output format configuration; wrong type for media type, expected string (e.g. text/html), got %T", vvi)
} }
} }
} }
@ -379,7 +377,7 @@ func decode(mediaTypes media.Types, input any, output *Format) error {
} }
if err = decoder.Decode(input); err != nil { if err = decoder.Decode(input); err != nil {
return errors.Wrap(err, "failed to decode output format configuration") return fmt.Errorf("failed to decode output format configuration: %w", err)
} }
return nil return nil

View file

@ -26,7 +26,6 @@ import (
xml "github.com/clbanning/mxj/v2" xml "github.com/clbanning/mxj/v2"
toml "github.com/pelletier/go-toml/v2" toml "github.com/pelletier/go-toml/v2"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cast" "github.com/spf13/cast"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
@ -74,7 +73,7 @@ func (d Decoder) UnmarshalToMap(data []byte, f Format) (map[string]any, error) {
func (d Decoder) UnmarshalFileToMap(fs afero.Fs, filename string) (map[string]any, error) { func (d Decoder) UnmarshalFileToMap(fs afero.Fs, filename string) (map[string]any, error) {
format := FormatFromString(filename) format := FormatFromString(filename)
if format == "" { if format == "" {
return nil, errors.Errorf("%q is not a valid configuration format", filename) return nil, fmt.Errorf("%q is not a valid configuration format", filename)
} }
data, err := afero.ReadFile(fs, filename) data, err := afero.ReadFile(fs, filename)
@ -106,7 +105,7 @@ func (d Decoder) UnmarshalStringTo(data string, typ any) (any, error) {
case float64: case float64:
return cast.ToFloat64E(data) return cast.ToFloat64E(data)
default: default:
return nil, errors.Errorf("unmarshal: %T not supported", typ) return nil, fmt.Errorf("unmarshal: %T not supported", typ)
} }
} }
@ -144,7 +143,7 @@ func (d Decoder) UnmarshalTo(data []byte, f Format, v any) error {
if err == nil { if err == nil {
xmlRootName, err := xmlRoot.Root() xmlRootName, err := xmlRoot.Root()
if err != nil { if err != nil {
return toFileError(f, errors.Wrap(err, "failed to unmarshal XML")) return toFileError(f, data, fmt.Errorf("failed to unmarshal XML: %w", err))
} }
xmlValue = xmlRoot[xmlRootName].(map[string]any) xmlValue = xmlRoot[xmlRootName].(map[string]any)
} }
@ -160,7 +159,7 @@ func (d Decoder) UnmarshalTo(data []byte, f Format, v any) error {
case YAML: case YAML:
err = yaml.Unmarshal(data, v) err = yaml.Unmarshal(data, v)
if err != nil { if err != nil {
return toFileError(f, errors.Wrap(err, "failed to unmarshal YAML")) return toFileError(f, data, fmt.Errorf("failed to unmarshal YAML: %w", err))
} }
// To support boolean keys, the YAML package unmarshals maps to // To support boolean keys, the YAML package unmarshals maps to
@ -191,14 +190,14 @@ func (d Decoder) UnmarshalTo(data []byte, f Format, v any) error {
return d.unmarshalCSV(data, v) return d.unmarshalCSV(data, v)
default: default:
return errors.Errorf("unmarshal of format %q is not supported", f) return fmt.Errorf("unmarshal of format %q is not supported", f)
} }
if err == nil { if err == nil {
return nil return nil
} }
return toFileError(f, errors.Wrap(err, "unmarshal failed")) return toFileError(f, data, fmt.Errorf("unmarshal failed: %w", err))
} }
func (d Decoder) unmarshalCSV(data []byte, v any) error { func (d Decoder) unmarshalCSV(data []byte, v any) error {
@ -215,7 +214,7 @@ func (d Decoder) unmarshalCSV(data []byte, v any) error {
case *any: case *any:
*v.(*any) = records *v.(*any) = records
default: default:
return errors.Errorf("CSV cannot be unmarshaled into %T", v) return fmt.Errorf("CSV cannot be unmarshaled into %T", v)
} }
@ -260,8 +259,8 @@ func (d Decoder) unmarshalORG(data []byte, v any) error {
return nil return nil
} }
func toFileError(f Format, err error) error { func toFileError(f Format, data []byte, err error) error {
return herrors.ToFileError(string(f), err) return herrors.NewFileError(fmt.Sprintf("_stream.%s", f), err).UpdateContent(bytes.NewReader(data), nil)
} }
// stringifyMapKeys recurses into in and changes all instances of // stringifyMapKeys recurses into in and changes all instances of

View file

@ -15,11 +15,11 @@ package pageparser
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"github.com/gohugoio/hugo/parser/metadecoders" "github.com/gohugoio/hugo/parser/metadecoders"
"github.com/pkg/errors"
) )
// Result holds the parse result. // Result holds the parse result.
@ -102,7 +102,7 @@ func ParseMain(r io.Reader, cfg Config) (Result, error) {
func parseSection(r io.Reader, cfg Config, start stateFunc) (Result, error) { func parseSection(r io.Reader, cfg Config, start stateFunc) (Result, error) {
b, err := ioutil.ReadAll(r) b, err := ioutil.ReadAll(r)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to read page content") return nil, fmt.Errorf("failed to read page content: %w", err)
} }
return parseBytes(b, cfg, start) return parseBytes(b, cfg, start)
} }

View file

@ -15,6 +15,7 @@ package publisher
import ( import (
"errors" "errors"
"fmt"
"io" "io"
"net/url" "net/url"
"sync/atomic" "sync/atomic"
@ -104,7 +105,7 @@ func (p DestinationPublisher) Publish(d Descriptor) error {
defer bp.PutBuffer(b) defer bp.PutBuffer(b)
if err := transformers.Apply(b, d.Src); err != nil { if err := transformers.Apply(b, d.Src); err != nil {
return err return fmt.Errorf("failed to process %q: %w", d.TargetPath, err)
} }
// This is now what we write to disk. // This is now what we write to disk.

View file

@ -26,8 +26,9 @@ import (
"github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/hexec"
"errors"
"github.com/gohugoio/hugo/common/hugo" "github.com/gohugoio/hugo/common/hugo"
"github.com/pkg/errors"
) )
const commitPrefix = "releaser:" const commitPrefix = "releaser:"
@ -217,7 +218,7 @@ func (r *ReleaseHandler) release(releaseNotesFile string) error {
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
return errors.Wrap(err, "goreleaser failed") return fmt.Errorf("goreleaser failed: %w", err)
} }
return nil return nil
} }

View file

@ -38,9 +38,6 @@ import (
"github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/resources/resource"
"github.com/pkg/errors"
_errors "github.com/pkg/errors"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/resources/images" "github.com/gohugoio/hugo/resources/images"
@ -325,7 +322,7 @@ func (i *imageResource) doWithImageConfig(conf images.ImageConfig, f func(src im
}) })
if err != nil { if err != nil {
if i.root != nil && i.root.getFileInfo() != nil { if i.root != nil && i.root.getFileInfo() != nil {
return nil, errors.Wrapf(err, "image %q", i.root.getFileInfo().Meta().Filename) return nil, fmt.Errorf("image %q: %w", i.root.getFileInfo().Meta().Filename, err)
} }
} }
return img, nil return img, nil
@ -345,7 +342,7 @@ func (i *imageResource) decodeImageConfig(action, spec string) (images.ImageConf
func (i *imageResource) DecodeImage() (image.Image, error) { func (i *imageResource) DecodeImage() (image.Image, error) {
f, err := i.ReadSeekCloser() f, err := i.ReadSeekCloser()
if err != nil { if err != nil {
return nil, _errors.Wrap(err, "failed to open image for decode") return nil, fmt.Errorf("failed to open image for decode: %w", err)
} }
defer f.Close() defer f.Close()
img, _, err := image.Decode(f) img, _, err := image.Decode(f)

View file

@ -15,10 +15,9 @@ package images
import ( import (
"encoding/hex" "encoding/hex"
"fmt"
"image/color" "image/color"
"strings" "strings"
"github.com/pkg/errors"
) )
// AddColorToPalette adds c as the first color in p if not already there. // AddColorToPalette adds c as the first color in p if not already there.
@ -50,7 +49,7 @@ func hexStringToColor(s string) (color.Color, error) {
s = strings.TrimPrefix(s, "#") s = strings.TrimPrefix(s, "#")
if len(s) != 3 && len(s) != 6 { if len(s) != 3 && len(s) != 6 {
return nil, errors.Errorf("invalid color code: %q", s) return nil, fmt.Errorf("invalid color code: %q", s)
} }
s = strings.ToLower(s) s = strings.ToLower(s)

View file

@ -22,7 +22,7 @@ import (
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
"github.com/pkg/errors" "errors"
"github.com/bep/gowebp/libwebp/webpoptions" "github.com/bep/gowebp/libwebp/webpoptions"
@ -158,7 +158,7 @@ func DecodeConfig(m map[string]any) (ImagingConfig, error) {
if i.Cfg.Anchor != "" && i.Cfg.Anchor != smartCropIdentifier { if i.Cfg.Anchor != "" && i.Cfg.Anchor != smartCropIdentifier {
anchor, found := anchorPositions[i.Cfg.Anchor] anchor, found := anchorPositions[i.Cfg.Anchor]
if !found { if !found {
return i, errors.Errorf("invalid anchor value %q in imaging config", i.Anchor) return i, fmt.Errorf("invalid anchor value %q in imaging config", i.Anchor)
} }
i.Anchor = anchor i.Anchor = anchor
} else { } else {
@ -263,7 +263,7 @@ func DecodeImageConfig(action, config string, defaults ImagingConfig, sourceForm
return c, errors.New("must provide Width or Height") return c, errors.New("must provide Width or Height")
} }
default: default:
return c, errors.Errorf("BUG: unknown action %q encountered while decoding image configuration", c.Action) return c, fmt.Errorf("BUG: unknown action %q encountered while decoding image configuration", c.Action)
} }
if c.FilterStr == "" { if c.FilterStr == "" {

View file

@ -34,8 +34,9 @@ import (
"golang.org/x/image/bmp" "golang.org/x/image/bmp"
"golang.org/x/image/tiff" "golang.org/x/image/tiff"
"errors"
"github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/hugio"
"github.com/pkg/errors"
) )
func NewImage(f Format, proc *ImageProcessor, img image.Image, s Spec) *Image { func NewImage(f Format, proc *ImageProcessor, img image.Image, s Spec) *Image {
@ -163,7 +164,7 @@ func (i *Image) initConfig() error {
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "failed to load image config") return fmt.Errorf("failed to load image config: %w", err)
} }
return nil return nil
@ -239,7 +240,7 @@ func (p *ImageProcessor) ApplyFiltersFromConfig(src image.Image, conf ImageConfi
case "fit": case "fit":
filters = append(filters, gift.ResizeToFit(conf.Width, conf.Height, conf.Filter)) filters = append(filters, gift.ResizeToFit(conf.Width, conf.Height, conf.Filter))
default: default:
return nil, errors.Errorf("unsupported action: %q", conf.Action) return nil, fmt.Errorf("unsupported action: %q", conf.Action)
} }
img, err := p.Filter(src, filters...) img, err := p.Filter(src, filters...)

View file

@ -20,7 +20,7 @@ import (
"path/filepath" "path/filepath"
"reflect" "reflect"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
@ -55,15 +55,15 @@ var (
func Generate(c *codegen.Inspector) error { func Generate(c *codegen.Inspector) error {
if err := generateMarshalJSON(c); err != nil { if err := generateMarshalJSON(c); err != nil {
return errors.Wrap(err, "failed to generate JSON marshaler") return fmt.Errorf("failed to generate JSON marshaler: %w", err)
} }
if err := generateDeprecatedWrappers(c); err != nil { if err := generateDeprecatedWrappers(c); err != nil {
return errors.Wrap(err, "failed to generate deprecate wrappers") return fmt.Errorf("failed to generate deprecate wrappers: %w", err)
} }
if err := generateFileIsZeroWrappers(c); err != nil { if err := generateFileIsZeroWrappers(c); err != nil {
return errors.Wrap(err, "failed to generate file wrappers") return fmt.Errorf("failed to generate file wrappers: %w", err)
} }
return nil return nil

View file

@ -14,13 +14,13 @@
package page package page
import ( import (
"fmt"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/hugofs/glob" "github.com/gohugoio/hugo/hugofs/glob"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
) )
// A PageMatcher can be used to match a Page with Glob patterns. // A PageMatcher can be used to match a Page with Glob patterns.
@ -132,7 +132,7 @@ func DecodePageMatcher(m any, v *PageMatcher) error {
} }
} }
if !found { if !found {
return errors.Errorf("%q did not match a valid Page Kind", v.Kind) return fmt.Errorf("%q did not match a valid Page Kind", v.Kind)
} }
} }

View file

@ -14,11 +14,11 @@
package page package page
import ( import (
"fmt"
"sync" "sync"
"github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/related" "github.com/gohugoio/hugo/related"
"github.com/pkg/errors"
"github.com/spf13/cast" "github.com/spf13/cast"
) )
@ -108,7 +108,7 @@ func (p Pages) withInvertedIndex(search func(idx *related.InvertedIndex) ([]rela
d, ok := p[0].(InternalDependencies) d, ok := p[0].(InternalDependencies)
if !ok { if !ok {
return nil, errors.Errorf("invalid type %T in related search", p[0]) return nil, fmt.Errorf("invalid type %T in related search", p[0])
} }
cache := d.GetRelatedDocsHandler() cache := d.GetRelatedDocsHandler()

View file

@ -23,7 +23,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
) )

View file

@ -31,7 +31,7 @@ import (
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
@ -633,7 +633,7 @@ func (fi *resourceFileInfo) hash() (string, error) {
var f hugio.ReadSeekCloser var f hugio.ReadSeekCloser
f, err = fi.ReadSeekCloser() f, err = fi.ReadSeekCloser()
if err != nil { if err != nil {
err = errors.Wrap(err, "failed to open source file") err = fmt.Errorf("failed to open source file: %w", err)
return return
} }
defer f.Close() defer f.Close()

View file

@ -16,6 +16,7 @@ package create
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"mime" "mime"
@ -34,7 +35,6 @@ import (
"github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/resources/resource"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
) )
type HTTPError struct { type HTTPError struct {
@ -77,7 +77,7 @@ func toHTTPError(err error, res *http.Response) *HTTPError {
func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resource, error) { func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resource, error) {
rURL, err := url.Parse(uri) rURL, err := url.Parse(uri)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to parse URL for resource %s", uri) return nil, fmt.Errorf("failed to parse URL for resource %s: %w", uri, err)
} }
resourceID := calculateResourceID(uri, optionsm) resourceID := calculateResourceID(uri, optionsm)
@ -85,7 +85,7 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou
_, httpResponse, err := c.cacheGetResource.GetOrCreate(resourceID, func() (io.ReadCloser, error) { _, httpResponse, err := c.cacheGetResource.GetOrCreate(resourceID, func() (io.ReadCloser, error) {
options, err := decodeRemoteOptions(optionsm) options, err := decodeRemoteOptions(optionsm)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to decode options for resource %s", uri) return nil, fmt.Errorf("failed to decode options for resource %s: %w", uri, err)
} }
if err := c.validateFromRemoteArgs(uri, options); err != nil { if err := c.validateFromRemoteArgs(uri, options); err != nil {
return nil, err return nil, err
@ -93,7 +93,7 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou
req, err := http.NewRequest(options.Method, uri, options.BodyReader()) req, err := http.NewRequest(options.Method, uri, options.BodyReader())
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to create request for resource %s", uri) return nil, fmt.Errorf("failed to create request for resource %s: %w", uri, err)
} }
addDefaultHeaders(req) addDefaultHeaders(req)
@ -113,7 +113,7 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou
if res.StatusCode != http.StatusNotFound { if res.StatusCode != http.StatusNotFound {
if res.StatusCode < 200 || res.StatusCode > 299 { if res.StatusCode < 200 || res.StatusCode > 299 {
return nil, toHTTPError(errors.Errorf("failed to fetch remote resource: %s", http.StatusText(res.StatusCode)), res) return nil, toHTTPError(fmt.Errorf("failed to fetch remote resource: %s", http.StatusText(res.StatusCode)), res)
} }
} }
@ -137,7 +137,7 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou
body, err := ioutil.ReadAll(res.Body) body, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to read remote resource %q", uri) return nil, fmt.Errorf("failed to read remote resource %q: %w", uri, err)
} }
filename := path.Base(rURL.Path) filename := path.Base(rURL.Path)
@ -172,7 +172,7 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou
// Now resolve the media type primarily using the content. // Now resolve the media type primarily using the content.
mediaType := media.FromContent(c.rs.MediaTypes, extensionHints, body) mediaType := media.FromContent(c.rs.MediaTypes, extensionHints, body)
if mediaType.IsZero() { if mediaType.IsZero() {
return nil, errors.Errorf("failed to resolve media type for remote resource %q", uri) return nil, fmt.Errorf("failed to resolve media type for remote resource %q", uri)
} }
resourceID = filename[:len(filename)-len(path.Ext(filename))] + "_" + resourceID + mediaType.FirstSuffix.FullSuffix resourceID = filename[:len(filename)-len(path.Ext(filename))] + "_" + resourceID + mediaType.FirstSuffix.FullSuffix

View file

@ -22,7 +22,6 @@ import (
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/resources/resource"
"github.com/pkg/errors"
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
@ -85,7 +84,7 @@ func AssignMetadata(metadata []map[string]any, resources ...resource.Resource) e
glob, err := glob.GetGlob(srcKey) glob, err := glob.GetGlob(srcKey)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to match resource with metadata") return fmt.Errorf("failed to match resource with metadata: %w", err)
} }
match := glob.Match(resourceSrcKey) match := glob.Match(resourceSrcKey)

View file

@ -15,6 +15,7 @@ package babel
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
@ -34,7 +35,6 @@ import (
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/resources/resource"
"github.com/pkg/errors"
) )
// Options from https://babeljs.io/docs/en/options // Options from https://babeljs.io/docs/en/options
@ -141,7 +141,7 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile) configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile)
if configFile == "" && t.options.Config != "" { if configFile == "" && t.options.Config != "" {
// Only fail if the user specified config file is not found. // Only fail if the user specified config file is not found.
return errors.Errorf("babel config %q not found:", configFile) return fmt.Errorf("babel config %q not found:", configFile)
} }
} }
@ -203,7 +203,7 @@ func (t *babelTransformation) Transform(ctx *resources.ResourceTransformationCtx
if hexec.IsNotFound(err) { if hexec.IsNotFound(err) {
return herrors.ErrFeatureNotAvailable return herrors.ErrFeatureNotAvailable
} }
return errors.Wrap(err, errBuf.String()) return fmt.Errorf(errBuf.String()+": %w", err)
} }
content, err := ioutil.ReadAll(compileOutput) content, err := ioutil.ReadAll(compileOutput)

View file

@ -19,14 +19,13 @@ import (
"crypto/sha512" "crypto/sha512"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"fmt"
"hash" "hash"
"html/template" "html/template"
"io" "io"
"github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/resources/internal"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/resources/resource"
) )
@ -92,7 +91,7 @@ func newHash(algo string) (hash.Hash, error) {
case "sha512": case "sha512":
return sha512.New(), nil return sha512.New(), nil
default: default:
return nil, errors.Errorf("unsupported crypto algo: %q, use either md5, sha256, sha384 or sha512", algo) return nil, fmt.Errorf("unsupported crypto algo: %q, use either md5, sha256, sha384 or sha512", algo)
} }
} }

View file

@ -22,13 +22,14 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/pkg/errors" "errors"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/text"
"github.com/gohugoio/hugo/hugolib/filesystems" "github.com/gohugoio/hugo/hugolib/filesystems"
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
@ -109,13 +110,13 @@ func (t *buildTransformation) Transform(ctx *resources.ResourceTransformationCtx
for i, ext := range opts.Inject { for i, ext := range opts.Inject {
impPath := filepath.FromSlash(ext) impPath := filepath.FromSlash(ext)
if filepath.IsAbs(impPath) { if filepath.IsAbs(impPath) {
return errors.Errorf("inject: absolute paths not supported, must be relative to /assets") return fmt.Errorf("inject: absolute paths not supported, must be relative to /assets")
} }
m := resolveComponentInAssets(t.c.rs.Assets.Fs, impPath) m := resolveComponentInAssets(t.c.rs.Assets.Fs, impPath)
if m == nil { if m == nil {
return errors.Errorf("inject: file %q not found", ext) return fmt.Errorf("inject: file %q not found", ext)
} }
opts.Inject[i] = m.Filename opts.Inject[i] = m.Filename
@ -157,10 +158,12 @@ func (t *buildTransformation) Transform(ctx *resources.ResourceTransformationCtx
} }
if err == nil { if err == nil {
fe := herrors.NewFileError("js", 0, loc.Line, loc.Column, errors.New(msg.Text)) fe := herrors.NewFileError(path, errors.New(msg.Text)).
err, _ := herrors.WithFileContext(fe, path, f, herrors.SimpleLineMatcher) UpdatePosition(text.Position{Offset: -1, LineNumber: loc.Line, ColumnNumber: loc.Column}).
UpdateContent(f, herrors.SimpleLineMatcher)
f.Close() f.Close()
return err return fe
} }
return fmt.Errorf("%s", msg.Text) return fmt.Errorf("%s", msg.Text)

View file

@ -21,7 +21,6 @@ import (
"strings" "strings"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/pkg/errors"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/evanw/esbuild/pkg/api" "github.com/evanw/esbuild/pkg/api"
@ -251,7 +250,7 @@ func createBuildPlugins(c *Client, opts Options) ([]api.Plugin, error) {
func(args api.OnLoadArgs) (api.OnLoadResult, error) { func(args api.OnLoadArgs) (api.OnLoadResult, error) {
b, err := ioutil.ReadFile(args.Path) b, err := ioutil.ReadFile(args.Path)
if err != nil { if err != nil {
return api.OnLoadResult{}, errors.Wrapf(err, "failed to read %q", args.Path) return api.OnLoadResult{}, fmt.Errorf("failed to read %q: %w", args.Path, err)
} }
c := string(b) c := string(b)
return api.OnLoadResult{ return api.OnLoadResult{
@ -274,7 +273,7 @@ func createBuildPlugins(c *Client, opts Options) ([]api.Plugin, error) {
b, err := json.Marshal(params) b, err := json.Marshal(params)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to marshal params") return nil, fmt.Errorf("failed to marshal params: %w", err)
} }
bs := string(b) bs := string(b)
paramsPlugin := api.Plugin{ paramsPlugin := api.Plugin{

View file

@ -17,6 +17,7 @@ import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"path" "path"
@ -36,8 +37,9 @@ import (
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cast" "github.com/spf13/cast"
"errors"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/pkg/errors"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
@ -161,7 +163,7 @@ func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationC
configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile) configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile)
if configFile == "" && t.options.Config != "" { if configFile == "" && t.options.Config != "" {
// Only fail if the user specified config file is not found. // Only fail if the user specified config file is not found.
return errors.Errorf("postcss config %q not found:", configFile) return fmt.Errorf("postcss config %q not found:", configFile)
} }
} }
@ -388,15 +390,9 @@ func (imp *importResolver) toFileError(output string) error {
if err != nil { if err != nil {
return inErr return inErr
} }
realFilename := fi.(hugofs.FileMetaInfo).Meta().Filename realFilename := fi.(hugofs.FileMetaInfo).Meta().Filename
ferr := herrors.NewFileError("css", -1, file.Offset+1, 1, inErr) return herrors.NewFileErrorFromFile(inErr, file.Filename, realFilename, hugofs.Os, herrors.SimpleLineMatcher)
werr, ok := herrors.WithFileContextForFile(ferr, realFilename, file.Filename, imp.fs, herrors.SimpleLineMatcher)
if !ok {
return ferr
}
return werr
} }

View file

@ -15,12 +15,13 @@
package templates package templates
import ( import (
"fmt"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/internal" "github.com/gohugoio/hugo/resources/internal"
"github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/resources/resource"
"github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/tpl"
"github.com/pkg/errors"
) )
// Client contains methods to perform template processing of Resource objects. // Client contains methods to perform template processing of Resource objects.
@ -55,7 +56,7 @@ func (t *executeAsTemplateTransform) Transform(ctx *resources.ResourceTransforma
tplStr := helpers.ReaderToString(ctx.From) tplStr := helpers.ReaderToString(ctx.From)
templ, err := t.t.TextTmpl().Parse(ctx.InPath, tplStr) templ, err := t.t.TextTmpl().Parse(ctx.InPath, tplStr)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to parse Resource %q as Template:", ctx.InPath) return fmt.Errorf("failed to parse Resource %q as Template:: %w", ctx.InPath, err)
} }
ctx.OutPath = t.targetPath ctx.OutPath = t.targetPath

View file

@ -120,18 +120,8 @@ func (t *transform) Transform(ctx *resources.ResourceTransformationCtx) error {
return m.Offset+len(m.Line) >= start.Offset && strings.Contains(m.Line, context) return m.Offset+len(m.Line) >= start.Offset && strings.Contains(m.Line, context)
} }
ferr, ok := herrors.WithFileContextForFile( return herrors.NewFileErrorFromFile(sassErr, filename, filename, hugofs.Os, offsetMatcher)
herrors.NewFileError("scss", -1, -1, start.Column, sassErr),
filename,
filename,
hugofs.Os,
offsetMatcher)
if !ok {
return sassErr
}
return ferr
} }
return err return err
} }

View file

@ -28,7 +28,6 @@ import (
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources"
"github.com/pkg/errors"
) )
// Used in tests. This feature requires Hugo to be built with the extended tag. // Used in tests. This feature requires Hugo to be built with the extended tag.
@ -172,7 +171,7 @@ func (c *Client) toCSS(options libsass.Options, dst io.Writer, src io.Reader) (l
in := helpers.ReaderToString(src) in := helpers.ReaderToString(src)
// See https://github.com/gohugoio/hugo/issues/7059 // See https://github.com/gohugoio/hugo/issues/7059
// We need to preserver the regular CSS imports. This is by far // We need to preserve the regular CSS imports. This is by far
// a perfect solution, and only works for the main entry file, but // a perfect solution, and only works for the main entry file, but
// that should cover many use cases, e.g. using SCSS as a preprocessor // that should cover many use cases, e.g. using SCSS as a preprocessor
// for Tailwind. // for Tailwind.
@ -181,7 +180,7 @@ func (c *Client) toCSS(options libsass.Options, dst io.Writer, src io.Reader) (l
res, err = transpiler.Execute(in) res, err = transpiler.Execute(in)
if err != nil { if err != nil {
return res, errors.Wrap(err, "SCSS processing failed") return res, fmt.Errorf("SCSS processing failed: %w", err)
} }
out := res.CSS out := res.CSS

View file

@ -24,8 +24,6 @@ import (
"github.com/gohugoio/hugo/common/paths" "github.com/gohugoio/hugo/common/paths"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/resources/images" "github.com/gohugoio/hugo/resources/images"
"github.com/gohugoio/hugo/resources/images/exif" "github.com/gohugoio/hugo/resources/images/exif"
"github.com/spf13/afero" "github.com/spf13/afero"
@ -431,10 +429,10 @@ func (r *resourceAdapter) transform(publish, setContent bool) error {
errMsg = ". You need to install Babel, see https://gohugo.io/hugo-pipes/babel/" errMsg = ". You need to install Babel, see https://gohugo.io/hugo-pipes/babel/"
} }
return errors.Wrap(err, msg+errMsg) return fmt.Errorf(msg+errMsg+": %w", err)
} }
return errors.Wrap(err, msg) return fmt.Errorf(msg+": %w", err)
} }
var tryFileCache bool var tryFileCache bool
@ -461,7 +459,7 @@ func (r *resourceAdapter) transform(publish, setContent bool) error {
if err != nil { if err != nil {
return newErr(err) return newErr(err)
} }
return newErr(errors.Errorf("resource %q not found in file cache", key)) return newErr(fmt.Errorf("resource %q not found in file cache", key))
} }
transformedContentr = f transformedContentr = f
updates.sourceFs = cache.fileCache.Fs updates.sourceFs = cache.fileCache.Fs

View file

@ -14,6 +14,7 @@
package source package source
import ( import (
"fmt"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
@ -22,8 +23,6 @@ import (
"github.com/gohugoio/hugo/hugofs/files" "github.com/gohugoio/hugo/hugofs/files"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
@ -244,11 +243,11 @@ func (sp *SourceSpec) NewFileInfo(fi hugofs.FileMetaInfo) (*FileInfo, error) {
relPath := m.Path relPath := m.Path
if relPath == "" { if relPath == "" {
return nil, errors.Errorf("no Path provided by %v (%T)", m, m.Fs) return nil, fmt.Errorf("no Path provided by %v (%T)", m, m.Fs)
} }
if filename == "" { if filename == "" {
return nil, errors.Errorf("no Filename provided by %v (%T)", m, m.Fs) return nil, fmt.Errorf("no Filename provided by %v (%T)", m, m.Fs)
} }
relDir := filepath.Dir(relPath) relDir := filepath.Dir(relPath)

View file

@ -14,11 +14,10 @@
package source package source
import ( import (
"fmt"
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/hugofs"
) )
@ -49,7 +48,7 @@ func (f *Filesystem) Files() ([]File, error) {
f.filesInit.Do(func() { f.filesInit.Do(func() {
err := f.captureFiles() err := f.captureFiles()
if err != nil { if err != nil {
f.filesInitErr = errors.Wrap(err, "capture files") f.filesInitErr = fmt.Errorf("capture files: %w", err)
} }
}) })
return f.files, f.filesInitErr return f.files, f.filesInitErr

View file

@ -24,12 +24,13 @@ import (
"strings" "strings"
"time" "time"
"errors"
"github.com/gohugoio/hugo/common/collections" "github.com/gohugoio/hugo/common/collections"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"github.com/pkg/errors"
"github.com/spf13/cast" "github.com/spf13/cast"
) )
@ -736,7 +737,7 @@ func (ns *Namespace) Uniq(seq any) (any, error) {
case reflect.Array: case reflect.Array:
slice = reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), 0, 0) slice = reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), 0, 0)
default: default:
return nil, errors.Errorf("type %T not supported", seq) return nil, fmt.Errorf("type %T not supported", seq)
} }
seen := make(map[any]bool) seen := make(map[any]bool)

View file

@ -14,13 +14,14 @@
package collections package collections
import ( import (
"fmt"
"reflect" "reflect"
"strings" "strings"
"github.com/gohugoio/hugo/common/hreflect" "github.com/gohugoio/hugo/common/hreflect"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/pkg/errors" "errors"
) )
// Merge creates a copy of the final parameter and merges the preceding // Merge creates a copy of the final parameter and merges the preceding
@ -49,7 +50,7 @@ func (ns *Namespace) merge(src, dst any) (any, error) {
vdst, vsrc := reflect.ValueOf(dst), reflect.ValueOf(src) vdst, vsrc := reflect.ValueOf(dst), reflect.ValueOf(src)
if vdst.Kind() != reflect.Map { if vdst.Kind() != reflect.Map {
return nil, errors.Errorf("destination must be a map, got %T", dst) return nil, fmt.Errorf("destination must be a map, got %T", dst)
} }
if !hreflect.IsTruthfulValue(vsrc) { if !hreflect.IsTruthfulValue(vsrc) {
@ -57,11 +58,11 @@ func (ns *Namespace) merge(src, dst any) (any, error) {
} }
if vsrc.Kind() != reflect.Map { if vsrc.Kind() != reflect.Map {
return nil, errors.Errorf("source must be a map, got %T", src) return nil, fmt.Errorf("source must be a map, got %T", src)
} }
if vsrc.Type().Key() != vdst.Type().Key() { if vsrc.Type().Key() != vdst.Type().Key() {
return nil, errors.Errorf("incompatible map types, got %T to %T", src, dst) return nil, fmt.Errorf("incompatible map types, got %T to %T", src, dst)
} }
return mergeMap(vdst, vsrc).Interface(), nil return mergeMap(vdst, vsrc).Interface(), nil

View file

@ -18,8 +18,9 @@ import (
"reflect" "reflect"
"time" "time"
"errors"
"github.com/mitchellh/hashstructure" "github.com/mitchellh/hashstructure"
"github.com/pkg/errors"
) )
var ( var (
@ -103,7 +104,7 @@ func convertValue(v reflect.Value, to reflect.Type) (reflect.Value, error) {
case isNumber(kind): case isNumber(kind):
return convertNumber(v, kind) return convertNumber(v, kind)
default: default:
return reflect.Value{}, errors.Errorf("%s is not assignable to %s", v.Type(), to) return reflect.Value{}, fmt.Errorf("%s is not assignable to %s", v.Type(), to)
} }
} }

View file

@ -16,8 +16,6 @@ package collections
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/pkg/errors"
) )
// SymDiff returns the symmetric difference of s1 and s2. // SymDiff returns the symmetric difference of s1 and s2.
@ -54,7 +52,7 @@ func (ns *Namespace) SymDiff(s2, s1 any) (any, error) {
if ids1[key] != ids2[key] { if ids1[key] != ids2[key] {
v, err := convertValue(ev, sliceElemType) v, err := convertValue(ev, sliceElemType)
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "symdiff: failed to convert value") return nil, fmt.Errorf("symdiff: failed to convert value: %w", err)
} }
slice = reflect.Append(slice, v) slice = reflect.Append(slice, v)
} }

View file

@ -20,6 +20,7 @@ import (
"encoding/csv" "encoding/csv"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"net/http" "net/http"
"strings" "strings"
@ -35,7 +36,6 @@ import (
"github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/deps"
_errors "github.com/pkg/errors"
) )
// New returns a new instance of the data-namespaced template functions. // New returns a new instance of the data-namespaced template functions.
@ -69,7 +69,7 @@ func (ns *Namespace) GetCSV(sep string, args ...any) (d [][]string, err error) {
unmarshal := func(b []byte) (bool, error) { unmarshal := func(b []byte) (bool, error) {
if d, err = parseCSV(b, sep); err != nil { if d, err = parseCSV(b, sep); err != nil {
err = _errors.Wrapf(err, "failed to parse CSV file %s", url) err = fmt.Errorf("failed to parse CSV file %s: %w", url, err)
return true, err return true, err
} }
@ -80,7 +80,7 @@ func (ns *Namespace) GetCSV(sep string, args ...any) (d [][]string, err error) {
var req *http.Request var req *http.Request
req, err = http.NewRequest("GET", url, nil) req, err = http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
return nil, _errors.Wrapf(err, "failed to create request for getCSV for resource %s", url) return nil, fmt.Errorf("failed to create request for getCSV for resource %s: %w", url, err)
} }
// Add custom user headers. // Add custom user headers.
@ -109,7 +109,7 @@ func (ns *Namespace) GetJSON(args ...any) (any, error) {
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
return nil, _errors.Wrapf(err, "Failed to create request for getJSON resource %s", url) return nil, fmt.Errorf("Failed to create request for getJSON resource %s: %w", url, err)
} }
unmarshal := func(b []byte) (bool, error) { unmarshal := func(b []byte) (bool, error) {

View file

@ -15,14 +15,13 @@ package data
import ( import (
"bytes" "bytes"
"fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"path/filepath" "path/filepath"
"time" "time"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config"
@ -70,7 +69,7 @@ func (ns *Namespace) getRemote(cache *filecache.Cache, unmarshal func([]byte) (b
res.Body.Close() res.Body.Close()
if isHTTPError(res) { if isHTTPError(res) {
return nil, errors.Errorf("Failed to retrieve remote file: %s, body: %q", http.StatusText(res.StatusCode), b) return nil, fmt.Errorf("Failed to retrieve remote file: %s, body: %q", http.StatusText(res.StatusCode), b)
} }
retry, err = unmarshal(b) retry, err = unmarshal(b)

View file

@ -18,7 +18,7 @@ import (
"image" "image"
"sync" "sync"
"github.com/pkg/errors" "errors"
"github.com/gohugoio/hugo/resources/images" "github.com/gohugoio/hugo/resources/images"

View file

@ -19,8 +19,6 @@ import (
"errors" "errors"
"fmt" "fmt"
_errors "github.com/pkg/errors"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/resources" "github.com/gohugoio/hugo/resources"
) )
@ -64,7 +62,7 @@ func ResolveArgs(args []any) (resources.ResourceTransformer, map[string]any, err
m, err := maps.ToStringMapE(args[0]) m, err := maps.ToStringMapE(args[0])
if err != nil { if err != nil {
return nil, nil, _errors.Wrap(err, "invalid options type") return nil, nil, fmt.Errorf("invalid options type: %w", err)
} }
return r, m, nil return r, m, nil

View file

@ -20,9 +20,10 @@ import (
"strconv" "strconv"
"strings" "strings"
"errors"
"github.com/gohugoio/locales" "github.com/gohugoio/locales"
translators "github.com/gohugoio/localescompressed" translators "github.com/gohugoio/localescompressed"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/hreflect" "github.com/gohugoio/hugo/common/hreflect"
"github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/deps"
@ -49,7 +50,7 @@ func (ns *Namespace) Translate(id any, args ...any) (string, error) {
if len(args) > 0 { if len(args) > 0 {
if len(args) > 1 { if len(args) > 1 {
return "", errors.Errorf("wrong number of arguments, expecting at most 2, got %d", len(args)+1) return "", fmt.Errorf("wrong number of arguments, expecting at most 2, got %d", len(args)+1)
} }
templateData = args[0] templateData = args[0]
} }

View file

@ -14,11 +14,12 @@
package openapi3 package openapi3
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
gyaml "github.com/ghodss/yaml" gyaml "github.com/ghodss/yaml"
"github.com/pkg/errors" "errors"
kopenapi3 "github.com/getkin/kin-openapi/openapi3" kopenapi3 "github.com/getkin/kin-openapi/openapi3"
"github.com/gohugoio/hugo/cache/namedmemcache" "github.com/gohugoio/hugo/cache/namedmemcache"
@ -57,7 +58,7 @@ func (ns *Namespace) Unmarshal(r resource.UnmarshableResource) (*kopenapi3.T, er
v, err := ns.cache.GetOrCreate(key, func() (any, error) { v, err := ns.cache.GetOrCreate(key, func() (any, error) {
f := metadecoders.FormatFromMediaType(r.MediaType()) f := metadecoders.FormatFromMediaType(r.MediaType())
if f == "" { if f == "" {
return nil, errors.Errorf("MIME %q not supported", r.MediaType()) return nil, fmt.Errorf("MIME %q not supported", r.MediaType())
} }
reader, err := r.ReadSeekCloser() reader, err := r.ReadSeekCloser()

View file

@ -20,8 +20,9 @@ import (
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"errors"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/tpl/internal/resourcehelpers" "github.com/gohugoio/hugo/tpl/internal/resourcehelpers"
@ -162,7 +163,7 @@ func (ns *Namespace) GetRemote(args ...any) resource.Resource {
case *create.HTTPError: case *create.HTTPError:
return resources.NewErrorResource(resource.NewResourceError(v, v.Data)) return resources.NewErrorResource(resource.NewResourceError(v, v.Data))
default: default:
return resources.NewErrorResource(resource.NewResourceError(errors.Wrap(err, "error calling resources.GetRemote"), make(map[string]any))) return resources.NewErrorResource(resource.NewResourceError(fmt.Errorf("error calling resources.GetRemote: %w", err), make(map[string]any)))
} }
} }
@ -354,7 +355,7 @@ func (ns *Namespace) ToCSS(args ...any) (resource.Resource, error) {
case transpilerDart, transpilerLibSass: case transpilerDart, transpilerLibSass:
transpiler = cast.ToString(t) transpiler = cast.ToString(t)
default: default:
return nil, errors.Errorf("unsupported transpiler %q; valid values are %q or %q", t, transpilerLibSass, transpilerDart) return nil, fmt.Errorf("unsupported transpiler %q; valid values are %q or %q", t, transpilerLibSass, transpilerDart)
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show more