package filecache
import (
+ "fmt"
"path"
"path/filepath"
"strings"
"github.com/gohugoio/hugo/helpers"
+ "errors"
+
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
"github.com/spf13/afero"
)
}
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 == "" {
name := strings.ToLower(k)
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
if !v.isResourceDir {
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)
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)
}
}
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)
}
package filecache
import (
+ "fmt"
"io"
"os"
"github.com/gohugoio/hugo/hugofs"
- "github.com/pkg/errors"
"github.com/spf13/afero"
)
if os.IsNotExist(err) {
continue
}
- return counter, errors.Wrapf(err, "failed to prune cache %q", k)
+ return counter, fmt.Errorf("failed to prune cache %q: %w", k, err)
}
}
package commands
import (
- "bytes"
"errors"
"io/ioutil"
"net"
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()
-
- fe := herrors.UnwrapErrorWithFileContext(c.buildErr)
- if fe != nil {
- m["File"] = fe
- }
-
- if c.h.verbose {
- var b bytes.Buffer
- herrors.FprintStackTraceFromErr(&b, c.buildErr)
- m["StackTrace"] = b.String()
- }
+ ferrors := herrors.UnwrapFileErrorsWithErrorContext(c.buildErr)
+ m["Files"] = ferrors
return m
}
"github.com/gohugoio/hugo/parser"
"github.com/gohugoio/hugo/parser/metadecoders"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/hugolib"
"github.com/spf13/cobra"
fs := hugofs.Os
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
"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/loggers"
"github.com/gohugoio/hugo/common/terminal"
copyStaticFunc := func() error {
cnt, err := c.copyStatic()
if err != nil {
- return errors.Wrap(err, "Error copying static files")
+ return fmt.Errorf("Error copying static files: %w", err)
}
langCount = cnt
return nil
}
buildSitesFunc := func() error {
if err := c.buildSites(noBuildLock); err != nil {
- return errors.Wrap(err, "Error building site")
+ return fmt.Errorf("Error building site: %w", err)
}
return nil
}
f, err := os.Create(c.h.cpuprofile)
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 {
- return nil, errors.Wrap(err, "failed to start CPU profile")
+ return nil, fmt.Errorf("failed to start CPU profile: %w", err)
}
return func() {
pprof.StopCPUProfile()
f, err := os.Create(c.h.traceprofile)
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 {
- return nil, errors.Wrap(err, "failed to start trace")
+ return nil, fmt.Errorf("failed to start trace: %w", err)
}
return func() {
c.logger.Errorln(msg + ":\n")
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 {
import (
"bytes"
"errors"
+ "fmt"
"path/filepath"
"strings"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/parser/metadecoders"
- _errors "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/create"
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugofs"
for _, dir := range dirs {
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)
}
}
"github.com/gohugoio/hugo/common/paths"
"golang.org/x/sync/errgroup"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/livereload"
"github.com/gohugoio/hugo/config"
// We're only interested in the path
u, err := url.Parse(baseURL)
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 {
func removeErrorPrefixFromLog(content string) string {
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 {
isMultiHost := c.hugo().IsMultihost()
roots = []string{""}
}
- templ, err := c.hugo().TextTmpl().Parse("__default_server_error", buildErrorTemplate)
- if err != nil {
- return err
- }
-
srv := &fileServer{
baseURLs: baseURLs,
roots: roots,
c: c,
s: s,
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{}
err := c.hugo().Tmpl().Execute(templ, b, ctx)
return b, err
if strings.Contains(u.Host, ":") {
u.Host, _, err = net.SplitHostPort(u.Host)
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)
"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 {
var b bytes.Buffer
chain := transform.Chain{livereloadinject.New(baseURL)}
-// 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");
// you may not use this file except in compliance with the License.
"strings"
"github.com/gohugoio/hugo/common/text"
-
- "github.com/spf13/afero"
)
// LineMatcher contains the elements used to match an error to a line
return m.Position.LineNumber == m.LineNumber
}
-var _ text.Positioner = ErrorContext{}
-
// ErrorContext contains contextual information about an error. This will
// typically be the lines surrounding some problem in a file.
type ErrorContext struct {
// The position of the error in the Lines above. 0 based.
LinesPos int
- position text.Position
-
// The lexer to use for syntax highlighting.
// https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages
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 {
switch fileType {
case "html", "htm":
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)
}
-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 {
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)
if err != nil {
- return errCtx
+ return errCtx, pos
}
- pos := &errCtx.position
lepos := le.Position()
lines := strings.Split(string(b), "\n")
}
- return errCtx
+ return errCtx, pos
}
-// 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");
// you may not use this file except in compliance with the License.
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"})
- pos := location.Position()
c.Assert(pos.LineNumber, qt.Equals, 5)
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
+ }
+
+ c.Assert(locate(`This is THEONE`, lineMatcher).Lines, qt.DeepEquals, []string{"This is THEONE"})
- location = locateErrorInString(`L1
+ location, pos = locateErrorInString(`L1
This is THEONE
L2
`, 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.Lines, qt.DeepEquals, []string{"L1", "This is THEONE", "L2", ""})
- location = locateErrorInString(`This is THEONE
+ location = locate(`This is THEONE
L2
`, lineMatcher)
c.Assert(location.LinesPos, qt.Equals, 0)
c.Assert(location.Lines, qt.DeepEquals, []string{"This is THEONE", "L2", ""})
- location = locateErrorInString(`L1
+ location = locate(`L1
This THEONE
`, lineMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "This THEONE", ""})
c.Assert(location.LinesPos, qt.Equals, 1)
- location = locateErrorInString(`L1
+ location = locate(`L1
L2
This THEONE
`, lineMatcher)
c.Assert(location.Lines, qt.DeepEquals, []string{"L1", "L2", "This THEONE", ""})
c.Assert(location.LinesPos, qt.Equals, 2)
- location = locateErrorInString("NO MATCH", lineMatcher)
- c.Assert(location.Position().LineNumber, qt.Equals, -1)
+ location, pos = locateErrorInString("NO MATCH", lineMatcher)
+ c.Assert(pos.LineNumber, qt.Equals, -1)
c.Assert(location.LinesPos, qt.Equals, -1)
c.Assert(len(location.Lines), qt.Equals, 0)
return m.LineNumber == 6
}
- location = locateErrorInString(`A
+ location, pos = locateErrorInString(`A
B
C
D
J`, lineMatcher)
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)
// Test match EOF
return m.LineNumber == 4
}
- location = locateErrorInString(`A
+ location, pos = locateErrorInString(`A
B
C
`, lineMatcher)
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)
offsetMatcher := func(m LineMatcher) bool {
return m.Offset == 1
}
- location = locateErrorInString(`A
+ location, pos = locateErrorInString(`A
B
C
D
E`, offsetMatcher)
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)
}
"errors"
"fmt"
"io"
- "os"
"runtime"
"runtime/debug"
"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.
func PrintStackTrace(w io.Writer) {
buf := make([]byte, 1<<16)
-// 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");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
-// Unless required by applicable law or agreed to in writing, software
+// Unless required by applicable lfmtaw or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
import (
"encoding/json"
+ "fmt"
+ "io"
+ "path/filepath"
+ "github.com/gohugoio/hugo/common/paths"
"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,
// execute a template etc.
type FileError interface {
error
+ // ErroContext holds some context information about the error.
+ ErrorContext() *ErrorContext
+
text.Positioner
- // A string identifying the type of file, e.g. JSON, TOML, markdown etc.
- Type() string
+ // UpdatePosition updates the position of the error.
+ 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
+}
+
+// Unwrapper can unwrap errors created with fmt.Errorf.
+type Unwrapper interface {
+ Unwrap() error
}
-var _ FileError = (*fileError)(nil)
+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 {
- position text.Position
+ position text.Position
+ errorContext *ErrorContext
fileType string
cause error
}
+type fileErrorWithErrorContext struct {
+ *fileError
+}
+
+func (e *fileError) ErrorContext() *ErrorContext {
+ return e.errorContext
+}
+
// Position returns the text position of this error.
func (e fileError) Position() text.Position {
return e.position
}
-func (e *fileError) Type() string {
- return e.fileType
+func (e *fileError) Error() string {
+ return fmt.Sprintf("%s: %s", e.position, e.cause)
}
-func (e *fileError) Error() string {
- if e.cause == nil {
- 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")
+ }
+
+ // Filetype is used to determine the Chroma lexer to use.
+ fileType, pos := extractFileTypePos(err)
+ pos.Filename = name
+ if fileType == "" {
+ _, fileType = paths.FileAndExtNoDelimiter(filepath.Clean(name))
}
- return e.cause.Error()
+
+ if pos.LineNumber < 0 {
+ panic(fmt.Sprintf("invalid line number: %d", pos.LineNumber))
+ }
+
+ return &fileError{cause: err, fileType: fileType, position: pos}
+
}
-func (f *fileError) Cause() error {
- return f.cause
+// 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)
}
-// 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}
+// 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.
switch v := err.(type) {
case FileError:
return v
- case causer:
- err = v.Cause()
default:
- return nil
+ err = errors.Unwrap(err)
}
}
return nil
}
-// ToFileErrorWithOffset will return a new FileError with a line number
-// with the given offset from the original.
-func ToFileErrorWithOffset(fe FileError, offset int) FileError {
- pos := fe.Position()
- return ToFileErrorWithLineNumber(fe, pos.LineNumber+offset)
-}
-
-// 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
- }
-
- if lno > 0 || offset != -1 {
- return NewFileError(fileType, offset, lno, col, err)
+// UnwrapFileErrorsWithErrorContext tries to unwrap all FileError in err that has an ErrorContext.
+func UnwrapFileErrorsWithErrorContext(err error) []FileError {
+ var errs []FileError
+ for err != nil {
+ if v, ok := err.(FileError); ok && v.ErrorContext() != nil {
+ errs = append(errs, v)
}
+ err = errors.Unwrap(err)
}
- // Fall back to the pointing to line number 1.
- return NewFileError(fileType, -1, 1, 1, err)
+ return errs
}
func extractOffsetAndType(e error) (int, string) {
- e = errors.Cause(e)
switch v := e.(type) {
case *json.UnmarshalTypeError:
return int(v.Offset), "json"
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
+}
-// 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");
// you may not use this file except in compliance with the License.
package herrors
import (
+ "fmt"
+ "strings"
"testing"
- "github.com/pkg/errors"
+ "errors"
+
+ "github.com/gohugoio/hugo/common/text"
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()
c := qt.New(t)
{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 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)
- le, ok := got.(FileError)
- c.Assert(ok, qt.Equals, true)
- c.Assert(ok, qt.Equals, true, errMsg)
- pos := le.Position()
+ pos := got.Position()
c.Assert(pos.LineNumber, qt.Equals, test.lineNumber, 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))
}
}
import (
"regexp"
"strconv"
-
- "github.com/pkg/errors"
-
- "github.com/pelletier/go-toml/v2"
)
var lineNumberExtractors = []lineNumberExtractor{
// Template/shortcode parse errors
- newLineNumberErrHandlerFromRegexp(".*:(\\d+):(\\d*):"),
- newLineNumberErrHandlerFromRegexp(".*:(\\d+):"),
+ newLineNumberErrHandlerFromRegexp(`:(\d+):(\d*):`),
+ newLineNumberErrHandlerFromRegexp(`:(\d+):`),
- // TOML parse errors
- tomlLineNumberExtractor,
// YAML parse errors
- newLineNumberErrHandlerFromRegexp("line (\\d+):"),
+ newLineNumberErrHandlerFromRegexp(`line (\d+):`),
// i18n bundle errors
- newLineNumberErrHandlerFromRegexp("\\((\\d+),\\s(\\d*)"),
+ newLineNumberErrHandlerFromRegexp(`\((\d+),\s(\d*)`),
}
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 {
re := regexp.MustCompile(expression)
return extractLineNo(re)
return lno, col
}
- return -1, col
+ return 0, col
}
}
package hugio
import (
+ "fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
- "github.com/pkg/errors"
-
"github.com/spf13/afero"
)
}
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
package config
import (
+ "fmt"
"sort"
"strings"
"sync"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/common/types"
"github.com/gobwas/glob"
// There are some tricky infinite loop situations when dealing
// when the target does not have a trailing slash.
// 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
}
package config
import (
+ "fmt"
"os"
"path/filepath"
"strings"
"github.com/gohugoio/hugo/common/herrors"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/common/maps"
func FromFile(fs afero.Fs, filename string) (Provider, error) {
m, err := loadConfigFromFile(fs, filename)
if err != nil {
- return nil, herrors.WithFileContextForFileDefault(err, filename, fs)
+ return nil, herrors.NewFileErrorFromFile(err, filename, filename, fs, herrors.SimpleLineMatcher)
}
return NewFrom(m), nil
}
if err != nil {
// This will be used in error reporting, use the most specific value.
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
"github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/paths"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/hugofs/files"
}
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) {
- 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()
in, err := meta.Open()
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))
targetDir := filepath.Dir(targetFilename)
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)
w := hugofs.NewWalkway(walkCfg)
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
}
bb, err := afero.ReadFile(b.archeTypeFs, filename)
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
"strings"
"sync"
+ "errors"
+
"github.com/dustin/go-humanize"
"github.com/gobwas/glob"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/media"
- "github.com/pkg/errors"
"github.com/spf13/afero"
jww "github.com/spf13/jwalterweatherman"
"golang.org/x/text/unicode/norm"
"fmt"
"regexp"
+ "errors"
+
"github.com/gobwas/glob"
"github.com/gohugoio/hugo/config"
hglob "github.com/gohugoio/hugo/hugofs/glob"
"github.com/gohugoio/hugo/media"
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
)
const deploymentConfigKey = "deployment"
package deps
import (
+ "fmt"
"sync"
"sync/atomic"
"time"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/loggers"
func (d *Deps) LoadResources() error {
// Note that the translations need to be loaded before the templates.
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 {
- return errors.Wrap(err, "loading templates")
+ return fmt.Errorf("loading templates: %w", err)
}
return nil
securityConfig, err := security.DecodeConfig(cfg.Cfg)
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)
ps, err := helpers.NewPathSpec(fs, cfg.Language, logger)
if err != nil {
- return nil, errors.Wrap(err, "create PathSpec")
+ return nil, fmt.Errorf("create PathSpec: %w", err)
}
fileCaches, err := filecache.NewCaches(ps)
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{}
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/common/hugio"
- _errors "github.com/pkg/errors"
"github.com/spf13/afero"
)
if !exists {
err := fs.MkdirAll(cacheDir, 0777) // Before umask
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
package hugofs
import (
+ "fmt"
"os"
"path/filepath"
"strings"
- "github.com/pkg/errors"
-
"github.com/spf13/afero"
)
}
fi, err = l.fs.decorate(fi, filename)
if err != nil {
- return nil, errors.Wrap(err, "decorate")
+ return nil, fmt.Errorf("decorate: %w", err)
}
fisp = append(fisp, fi)
}
"github.com/gohugoio/hugo/hugofs/files"
"golang.org/x/text/unicode/norm"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/common/hreflect"
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/pkg/errors"
-
radix "github.com/armon/go-radix"
"github.com/spf13/afero"
)
fs = decorateDirs(fs, r.Meta)
fi, err := fs.Stat("")
if err != nil {
- return nil, errors.Wrap(err, "RootMappingFs.Dirs")
+ return nil, fmt.Errorf("RootMappingFs.Dirs: %w", err)
}
if !fi.IsDir() {
if fileCount > 1 {
// 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
package hugofs
import (
+ "fmt"
"os"
"syscall"
"time"
- "github.com/pkg/errors"
+ "errors"
"github.com/spf13/afero"
)
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 {
"github.com/gohugoio/hugo/common/loggers"
- "github.com/pkg/errors"
+ "errors"
"github.com/spf13/afero"
)
if w.checkErr(w.root, err) {
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)
}
if w.checkErr(path, err) {
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)
if w.checkErr(filename, err) {
return nil
}
- return walkFn(path, info, errors.Wrap(err, "walk: Readdir"))
+ return walkFn(path, info, fmt.Errorf("walk: Readdir: %w", err))
}
dirEntries = fileInfosToFileMetaInfos(fis)
"strings"
"testing"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/common/para"
"github.com/gohugoio/hugo/htesting"
"github.com/gohugoio/hugo/parser/metadecoders"
+ "errors"
+
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/modules"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/config/privacy"
}
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)
}
_, _, err := LoadConfig(ConfigSourceDescriptor{Fs: mm, Environment: "development", Filename: "hugo.toml", AbsConfigDir: "config"})
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.Position().Filename, qt.Equals, filepath.FromSlash("config/development/config.toml"))
}
package hugolib
import (
+ "fmt"
"io"
"path/filepath"
"strings"
"github.com/gohugoio/hugo/resources/page"
- "github.com/pkg/errors"
"github.com/spf13/afero"
)
}
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)
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)
}
templ, err := ps.s.TextTmpl().Parse("archetype.md", string(templateSource))
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)
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))
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/resources/page"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/hugofs/files"
p, k := b.getBundle(p)
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
}
"github.com/spf13/cast"
"github.com/gohugoio/hugo/common/para"
- "github.com/pkg/errors"
)
func newPageMaps(h *HugoSites) *pageMaps {
gi, err := s.h.gitInfoForPage(ps)
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
owners, err := s.h.codeownersForPage(ps)
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
} else {
taxonomy := m.s.taxonomies[viewName.plural]
if taxonomy == nil {
- walkErr = errors.Errorf("missing taxonomy: %s", viewName.plural)
+ walkErr = fmt.Errorf("missing taxonomy: %s", viewName.plural)
return true
}
m.taxonomyEntries.WalkPrefix(s, func(ss string, v any) bool {
package hugolib
import (
+ "fmt"
"strings"
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/hugofs"
"github.com/spf13/afero"
func (fi *fileInfo) Open() (afero.File, error) {
f, err := fi.FileInfo().Meta().Open()
if err != nil {
- err = errors.Wrap(err, "fileInfo")
+ err = fmt.Errorf("fileInfo: %w", err)
}
return f, err
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/modules"
hpaths "github.com/gohugoio/hugo/common/paths"
}
- 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
builder := newSourceFilesystemsBuilder(p, logger, b)
sourceFilesystems, err := builder.Build()
if err != nil {
- return nil, errors.Wrap(err, "build filesystems")
+ return nil, fmt.Errorf("build filesystems: %w", err)
}
b.SourceFilesystems = sourceFilesystems
if b.theBigFs == nil {
theBigFs, err := b.createMainOverlayFs(b.p)
if err != nil {
- return nil, errors.Wrap(err, "create main fs")
+ return nil, fmt.Errorf("create main fs: %w", err)
}
b.theBigFs = theBigFs
contentFs, err := hugofs.NewLanguageFs(b.p.LanguagesDefaultFirst.AsOrdinalSet(), contentBfs)
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)
import (
"context"
+ "fmt"
"io"
"path/filepath"
"sort"
"github.com/gohugoio/hugo/output"
"github.com/gohugoio/hugo/parser/metadecoders"
+ "errors"
+
"github.com/gohugoio/hugo/common/para"
"github.com/gohugoio/hugo/hugofs"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/source"
func (h *HugoSites) Data() map[string]any {
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 h.data
for j, err := range errors {
// If this is in server mode, we want to return an error to the client
// with a file context, if possible.
- if herrors.UnwrapErrorWithFileContext(err) != nil {
+ if herrors.UnwrapFileError(err) != nil {
i = j
break
}
langConfig, err := newMultiLingualFromSites(cfg.Cfg, sites...)
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
h.init.data.Add(func() (any, error) {
err := h.loadData(h.PathSpec.BaseFs.Data.Dirs)
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
})
h.init.gitInfo.Add(func() (any, error) {
err := h.loadGitInfo()
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
})
var l configLoader
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
siteConfig, err := l.loadSiteConfig(s.language)
if err != nil {
- return errors.Wrap(err, "load site config")
+ return fmt.Errorf("load site config: %w", err)
}
s.siteConfigConfig = siteConfig
var err error
d, err = deps.New(cfg)
if err != nil {
- return errors.Wrap(err, "create deps")
+ return fmt.Errorf("create deps: %w", err)
}
d.OutputFormatsConfig = s.outputFormatsConfig
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 {
- return errors.Wrap(err, "load resources")
+ return fmt.Errorf("load resources: %w", err)
}
} else {
}
sites, err := createSitesFromConfig(cfg)
if err != nil {
- return nil, errors.Wrap(err, "from config")
+ return nil, fmt.Errorf("from config: %w", err)
}
return newHugoSites(cfg, sites...)
}
f, err := r.FileInfo().Meta().Open()
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()
if !ok {
return err
}
-
realFilename := fim.Meta().Filename
- err, _ = herrors.WithFileContextForFile(
- err,
- realFilename,
- realFilename,
- h.SourceSpec.Fs.Source,
- herrors.SimpleLineMatcher)
+ return herrors.NewFileErrorFromFile(err, realFilename, realFilename, h.SourceSpec.Fs.Source, herrors.SimpleLineMatcher)
- return err
}
func (h *HugoSites) readData(f source.File) (any, error) {
file, err := f.FileInfo().Meta().Open()
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()
content := helpers.ReaderToBytes(file)
"github.com/gohugoio/hugo/output"
- "github.com/pkg/errors"
+ "errors"
"github.com/fsnotify/fsnotify"
"github.com/gohugoio/hugo/helpers"
if !config.NoBuildLock {
unlock, err := h.BaseFs.LockBuild()
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()
}
if len(events) > 0 {
// Rebuild
if err := h.initRebuild(conf); err != nil {
- return errors.Wrap(err, "initRebuild")
+ return fmt.Errorf("initRebuild: %w", err)
}
} else {
if err := h.initSites(conf); err != nil {
- return errors.Wrap(err, "initSites")
+ return fmt.Errorf("initSites: %w", err)
}
}
}
trace.WithRegion(ctx, "process", f)
if err != nil {
- return errors.Wrap(err, "process")
+ return fmt.Errorf("process: %w", err)
}
f = func() {
import (
"fmt"
+ "os"
"path/filepath"
"strings"
"testing"
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))
- ferr := herrors.UnwrapErrorWithFileContext(err)
- t.c.Assert(ferr, qt.Not(qt.IsNil))
- return ferr
+ fe := herrors.UnwrapFileError(err)
+ t.c.Assert(fe, qt.Not(qt.IsNil))
+ return fe
}
func (t testSiteBuildErrorAsserter) assertLineNumber(lineNumber int, err error) {
+ t.c.Helper()
fe := t.getFileError(err)
t.c.Assert(fe.Position().LineNumber, qt.Equals, lineNumber, qt.Commentf(err.Error()))
}
fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
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())
},
},
fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
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())
},
},
fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
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())
},
},
},
},
{
- name: "Shortode execute failed",
+ name: "Shortcode execute failed",
fileType: shortcode,
fileFixer: func(content string) string {
return strings.Replace(content, ".Title", ".Titles", 1)
},
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
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
- a.assertErrorMessage(`content/myyaml.md:7:10": failed to render shortcode "sc"`, fe.Error())
- a.assertErrorMessage(`shortcodes/sc.html:4:22: executing "shortcodes/sc.html" at <.Page.Titles>: can't evaluate`, 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.c.Assert(fe.Position().LineNumber, qt.Equals, 7)
+
},
},
{
fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 7)
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())
},
},
name: "Invalid YAML front matter",
fileType: yamlcontent,
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) {
- a.assertLineNumber(2, err)
+ a.assertLineNumber(3, err)
},
},
{
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
fe := a.getFileError(err)
a.c.Assert(fe.Position().LineNumber, qt.Equals, 6)
- a.c.Assert(fe.ErrorContext.ChromaLexer, qt.Equals, "toml")
},
},
{
},
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
fe := a.getFileError(err)
-
a.c.Assert(fe.Position().LineNumber, qt.Equals, 3)
- a.c.Assert(fe.ErrorContext.ChromaLexer, qt.Equals, "json")
},
},
{
}
for _, test := range tests {
+ if test.name != "Invalid JSON front matter" {
+ continue
+ }
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
}
})
}
+
+}
+
+// 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
}
func (s *IntegrationTestBuilder) AssertIsFileError(err error) {
- var ferr *herrors.ErrorWithFileContext
- s.Assert(err, qt.ErrorAs, &ferr)
+ s.Assert(err, qt.ErrorAs, new(herrors.FileError))
}
func (s *IntegrationTestBuilder) AssertRenderCountContent(count int) {
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/parser/metadecoders"
+ "errors"
+
"github.com/gohugoio/hugo/parser/pageparser"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/output"
src, ok := r.(resource.Source)
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
}
// wrapError adds some more context to the given error if possible/needed
func (p *pageState) wrapError(err error) error {
- if _, ok := err.(*herrors.ErrorWithFileContext); ok {
- // Preserve the first file context.
- return err
+ if err == nil {
+ panic("wrapError with nil")
}
- var filename string
- if !p.File().IsZero() {
- filename = p.File().Filename()
+
+ if p.File().IsZero() {
+ // No more details to add.
+ return fmt.Errorf("%q: %w", p.Pathc(), err)
}
- err, _ = herrors.WithFileContextForFile(
- err,
- filename,
- 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
+ }
+ 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)
- return err
}
func (p *pageState) getContentConverter() converter.Converter {
iter := p.source.parsed.Iterator()
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)
}
m, err := metadecoders.Default.UnmarshalToMap(it.Val, f)
if err != nil {
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 {
return err
}
currShortcode, err := s.extractShortcode(ordinal, 0, iter)
if err != nil {
- return fail(errors.Wrap(err, "failed to extract shortcode"), it)
+ return fail(err, it)
}
currShortcode.pos = it.Pos
case it.IsEOF():
break Loop
case it.IsError():
- err := fail(errors.WithStack(errors.New(it.ValStr())), it)
+ err := fail(errors.New(it.ValStr()), it)
currShortcode.err = err
return err
}
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.
return err
}
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 {
- errors.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) 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)
- return herrors.NewFileError("md", -1, pos.LineNumber, pos.ColumnNumber, err)
+ return herrors.NewFileError("page.md", err).UpdatePosition(pos)
}
func (p *pageState) pathOrTitle() string {
"github.com/gohugoio/hugo/related"
"github.com/gohugoio/hugo/source"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config"
}
cp := p.s.ContentSpec.Converters.Get(markup)
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
"sync"
"unicode/utf8"
+ "errors"
+
"github.com/gohugoio/hugo/common/text"
"github.com/gohugoio/hugo/common/types/hstring"
"github.com/gohugoio/hugo/identity"
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
"github.com/spf13/cast"
"github.com/gohugoio/hugo/markup/converter/hooks"
}
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)
}
}
// Make sure to send the *pageState and not the *pageContentOutput to the template.
res, err := executeToString(p.p.s.Tmpl(), templ, p.p)
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
}
"github.com/gohugoio/hugo/common/text"
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
)
func newPageRef(p *pageState) pageRef {
func (p pageRef) ref(argsm map[string]any, source any) (string, error) {
args, s, err := p.decodeRefArgs(argsm)
if err != nil {
- return "", errors.Wrap(err, "invalid arguments to Ref")
+ return "", fmt.Errorf("invalid arguments to Ref: %w", err)
}
if s == nil {
func (p pageRef) relRef(argsm map[string]any, source any) (string, error) {
args, s, err := p.decodeRefArgs(argsm)
if err != nil {
- return "", errors.Wrap(err, "invalid arguments to Ref")
+ return "", fmt.Errorf("invalid arguments to Ref: %w", err)
}
if s == nil {
package hugolib
import (
- "github.com/pkg/errors"
+ "fmt"
"github.com/gohugoio/hugo/resources/page"
)
case nil:
return nil, nil
default:
- return nil, errors.Errorf("unwrapPage: %T not supported", in)
+ return nil, fmt.Errorf("unwrapPage: %T not supported", in)
}
}
"github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"github.com/gohugoio/hugo/common/herrors"
meta := fim.Meta()
f, err := meta.Open()
if err != nil {
- return errors.Wrap(err, "copyFile: failed to open")
+ return fmt.Errorf("copyFile: failed to open: %w", err)
}
s := p.m.s
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/modules"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/hugofs"
)
baseURLstr := cfg.GetString("baseURL")
baseURL, err := newBaseURLFromString(baseURLstr)
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"))
"github.com/gohugoio/hugo/helpers"
+ "errors"
+
"github.com/gohugoio/hugo/common/herrors"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/parser/pageparser"
"github.com/gohugoio/hugo/resources/page"
innerNewlineRegexp = "\n"
innerCleanupRegexp = `\A<p>(.*)</p>\n\z`
innerCleanupExpand = "$1"
+ pageFileErrorName = "page.md"
)
func renderShortcode(
var err error
tmpl, err = s.TextTmpl().Parse(templName, templStr)
if err != nil {
- fe := herrors.ToFileError("html", err)
- l1, l2 := p.posOffset(sc.pos).LineNumber, fe.Position().LineNumber
- fe = herrors.ToFileErrorWithLineNumber(fe, l1+l2-1)
+ fe := herrors.NewFileError(pageFileErrorName, err)
+ pos := fe.Position()
+ pos.LineNumber += p.posOffset(sc.pos).LineNumber
+ fe = fe.UpdatePosition(pos)
return "", false, p.wrapError(fe)
}
var found bool
tmpl, found = s.TextTmpl().Lookup(templName)
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 {
result, err := renderShortcodeWithPage(s.Tmpl(), tmpl, data)
if err != nil && sc.isInline {
- fe := herrors.ToFileError("html", err)
- l1, l2 := p.posFromPage(sc.pos).LineNumber, fe.Position().LineNumber
- fe = herrors.ToFileErrorWithLineNumber(fe, l1+l2-1)
+ fe := herrors.NewFileError("shortcode.md", err)
+ pos := fe.Position()
+ pos.LineNumber += p.posOffset(sc.pos).LineNumber
+ fe = fe.UpdatePosition(pos)
return "", false, fe
}
for _, v := range s.shortcodes {
s, more, err := renderShortcode(0, s.s, tplVariants, v, nil, p)
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
}
hasVariants = hasVariants || more
cnt := 0
nestedOrdinal := 0
nextLevel := level + 1
+ const errorPrefix = "failed to extract shortcode"
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:
// return that error, more specific
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() {
// Used to check if the template expects inner content.
templs := s.s.Tmpl().LookupVariants(sc.name)
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)
err := h.Execute(tmpl, buffer, data)
if err != nil {
- return "", errors.Wrap(err, "failed to process shortcode")
+ return "", fmt.Errorf("failed to process shortcode: %w", err)
}
return buffer.String(), nil
}
b := newTestSitesBuilder(t)
- b.WithContent("page.md", `---
+ b.WithContent("mypage.md", `---
title: "No Inner!"
---
{{< noinner >}}{{< /noinner >}}
"layouts/shortcodes/noinner.html", `No inner here.`)
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) {
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/publisher"
- "github.com/pkg/errors"
- _errors "github.com/pkg/errors"
"github.com/gohugoio/hugo/langs"
if cfg.Language.IsSet("related") {
relatedContentConfig, err = related.DecodeConfig(cfg.Language.GetParams("related"))
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 {
relatedContentConfig = related.DefaultConfig
var err error
cascade, err := page.DecodeCascade(cfg.Language.Get("cascade"))
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{
func (s *Site) process(config BuildCfg) (err error) {
if err = s.initialize(); err != nil {
- err = errors.Wrap(err, "initialize")
+ err = fmt.Errorf("initialize: %w", err)
return
}
if err = s.readAndProcessContent(config); err != nil {
- err = errors.Wrap(err, "readAndProcessContent")
+ err = fmt.Errorf("readAndProcessContent: %w", err)
return
}
return err
for name, me := range p.pageMenus.menus() {
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)
continue
}
}
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
}
"github.com/gohugoio/hugo/config"
+ "errors"
+
"github.com/gohugoio/hugo/output"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/resources/page/pagemeta"
err := <-errs
if err != nil {
- return errors.Wrap(err, "failed to render pages")
+ return fmt.Errorf("failed to render pages: %w", err)
}
return nil
}
"github.com/google/go-cmp/cmp"
"github.com/gohugoio/hugo/parser"
- "github.com/pkg/errors"
"github.com/fsnotify/fsnotify"
- "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config"
func (s *sitesBuilder) CreateSites() *sitesBuilder {
if err := s.CreateSitesE(); err != nil {
- herrors.PrintStackTraceFromErr(err)
s.Fatalf("Failed to create sites: %s", err)
}
"i18n",
} {
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)
}
}
}
}
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)
sites, err := NewHugoSites(depsCfg)
if err != nil {
- return errors.Wrap(err, "failed to create sites")
+ return fmt.Errorf("failed to create sites: %w", err)
}
s.H = sites
}
}
if err != nil && !shouldFail {
- herrors.PrintStackTraceFromErr(err)
s.Fatalf("Build failed: %s", err)
} else if err == nil && shouldFail {
s.Fatalf("Expected error")
"github.com/spf13/cast"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/config"
)
} else {
languages2, err = toSortedLanguages(cfg, languages)
if err != nil {
- return c, errors.Wrap(err, "Failed to parse multilingual config")
+ return c, fmt.Errorf("Failed to parse multilingual config: %w", err)
}
}
import (
"encoding/json"
+ "fmt"
"strings"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/source"
- _errors "github.com/pkg/errors"
)
// TranslationProvider provides translation handling, i.e. loading
func addTranslationFile(bundle *i18n.Bundle, r source.File) error {
f, err := r.FileInfo().Meta().Open()
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)
try := artificialLangTagPrefix + lang
_, err = language.Parse(try)
if err != nil {
- return _errors.Errorf("%q %s.", try, err)
+ return fmt.Errorf("%q: %s", try, err)
}
name = artificialLangTagPrefix + name
}
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
}
defer f.Close()
- err, _ = herrors.WithFileContext(
- inerr,
- realFilename,
- f,
- herrors.SimpleLineMatcher)
+ return herrors.NewFileError(realFilename, inerr).UpdateContent(f, herrors.SimpleLineMatcher)
- return err
}
package langs
import (
+ "fmt"
"sort"
"strings"
"sync"
"golang.org/x/text/collate"
"golang.org/x/text/language"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/common/htime"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config"
func (l *Language) loadLocation(tzStr string) error {
location, err := time.LoadLocation(tzStr)
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
"sync/atomic"
"time"
- "github.com/pkg/errors"
+ "errors"
)
// New creates a new empty Init.
package blackfriday_config
import (
+ "fmt"
+
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
)
// Default holds the default BlackFriday config.
func UpdateConfig(b Config, m map[string]any) (Config, error) {
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
}
"github.com/gohugoio/hugo/common/hugio"
- "github.com/pkg/errors"
+ "errors"
+
"github.com/spf13/afero"
)
// See https://github.com/gohugoio/hugo/issues/8239
// This is an error situation. We need something to vendor.
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())
targetFilename := filepath.Join(vendorDir, t.Path(), mount.Source)
fi, err := c.fs.Stat(sourceFilename)
if err != nil {
- return errors.Wrap(err, "failed to vendor module")
+ return fmt.Errorf("failed to vendor module: %w", err)
}
if fi.IsDir() {
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 {
targetDir := filepath.Dir(targetFilename)
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 {
- return errors.Wrap(err, "failed to copy module file to vendor")
+ return fmt.Errorf("failed to copy module file to vendor: %w", err)
}
}
}
_, err := c.fs.Stat(resourcesDir)
if 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)
}
}
_, err = c.fs.Stat(configDir)
if 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)
}
}
args = append([]string{"-d"}, args...)
}
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
}
func (c *Client) Init(path string) error {
err := c.runGo(context.Background(), c.logger.Out(), "mod", "init", path)
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)
out := ioutil.Discard
err := c.runGo(context.Background(), out, args...)
if err != nil {
- return errors.Wrap(err, "failed to download modules")
+ return fmt.Errorf("failed to download modules: %w", err)
}
return nil
}
}
err := c.runGo(context.Background(), b, args...)
if err != nil {
- return errors.Wrap(err, "failed to list modules")
+ return fmt.Errorf("failed to list modules: %w", err)
}
dec := json.NewDecoder(b)
if err == io.EOF {
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 {
_, ok := err.(*exec.ExitError)
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
return nil
}
- return errors.Errorf("go command failed: %s", stderr)
+ return fmt.Errorf("go command failed: %s", stderr)
}
}
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)
if filepath.IsAbs(modulePath) {
"github.com/rogpeppe/go-internal/module"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/config"
"github.com/spf13/afero"
// IsNotExist returns whether an error means that a module could not be found.
func IsNotExist(err error) bool {
- return errors.Cause(err) == ErrNotExist
+ return errors.Is(err, os.ErrNotExist)
}
// CreateProjectModule creates modules from the given config.
return nil, nil
}
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
}
}
}
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
}
line = strings.TrimSpace(line)
parts := strings.Fields(line)
if len(parts) != 2 {
- return errors.Errorf("invalid modules list: %q", filename)
+ return fmt.Errorf("invalid modules list: %q", filename)
}
path := parts[0]
targetBase = mnt.Target[0:idxPathSep]
}
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)
}
func (c *collector) wrapModuleNotFound(err error) error {
- err = errors.Wrap(ErrNotExist, err.Error())
+ err = fmt.Errorf(err.Error()+": %w", ErrNotExist)
if c.GoModulesFilename == "" {
return err
}
switch c.goBinaryStatus {
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:
- 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
"path/filepath"
"strings"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/config"
for _, repl := range c.Replacements {
parts := strings.Split(repl, "->")
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])
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/hugofs"
"github.com/spf13/afero"
if err == nil {
// Preserve the original in package.hugo.json.
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 {
// Create one.
masterFilename := meta.Filename
f, err := meta.Open()
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)
f.Close()
f, err := meta.Open()
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)
f.Close()
}
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.
encoder.SetEscapeHTML(false)
encoder.SetIndent("", strings.Repeat(" ", 2))
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 {
- 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
"sort"
"strings"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/compare"
}
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
package navigation
import (
+ "fmt"
+
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
- "github.com/pkg/errors"
"github.com/spf13/cast"
)
}
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
"sort"
"strings"
- "github.com/pkg/errors"
-
"github.com/mitchellh/mapstructure"
"github.com/gohugoio/hugo/media"
}
dataVal.SetMapIndex(key, reflect.ValueOf(mediaType))
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)
}
}
}
}
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
xml "github.com/clbanning/mxj/v2"
toml "github.com/pelletier/go-toml/v2"
- "github.com/pkg/errors"
"github.com/spf13/afero"
"github.com/spf13/cast"
jww "github.com/spf13/jwalterweatherman"
func (d Decoder) UnmarshalFileToMap(fs afero.Fs, filename string) (map[string]any, error) {
format := FormatFromString(filename)
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)
case float64:
return cast.ToFloat64E(data)
default:
- return nil, errors.Errorf("unmarshal: %T not supported", typ)
+ return nil, fmt.Errorf("unmarshal: %T not supported", typ)
}
}
if err == nil {
xmlRootName, err := xmlRoot.Root()
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)
}
case YAML:
err = yaml.Unmarshal(data, v)
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
return d.unmarshalCSV(data, v)
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 {
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 {
case *any:
*v.(*any) = records
default:
- return errors.Errorf("CSV cannot be unmarshaled into %T", v)
+ return fmt.Errorf("CSV cannot be unmarshaled into %T", v)
}
return nil
}
-func toFileError(f Format, err error) error {
- return herrors.ToFileError(string(f), err)
+func toFileError(f Format, data []byte, err error) error {
+ return herrors.NewFileError(fmt.Sprintf("_stream.%s", f), err).UpdateContent(bytes.NewReader(data), nil)
}
// stringifyMapKeys recurses into in and changes all instances of
import (
"bytes"
+ "fmt"
"io"
"io/ioutil"
"github.com/gohugoio/hugo/parser/metadecoders"
- "github.com/pkg/errors"
)
// Result holds the parse result.
func parseSection(r io.Reader, cfg Config, start stateFunc) (Result, error) {
b, err := ioutil.ReadAll(r)
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)
}
import (
"errors"
+ "fmt"
"io"
"net/url"
"sync/atomic"
defer bp.PutBuffer(b)
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.
"github.com/gohugoio/hugo/common/hexec"
+ "errors"
+
"github.com/gohugoio/hugo/common/hugo"
- "github.com/pkg/errors"
)
const commitPrefix = "releaser:"
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
- return errors.Wrap(err, "goreleaser failed")
+ return fmt.Errorf("goreleaser failed: %w", err)
}
return nil
}
"github.com/gohugoio/hugo/resources/resource"
- "github.com/pkg/errors"
- _errors "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/resources/images"
})
if err != 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
func (i *imageResource) DecodeImage() (image.Image, error) {
f, err := i.ReadSeekCloser()
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()
img, _, err := image.Decode(f)
import (
"encoding/hex"
+ "fmt"
"image/color"
"strings"
-
- "github.com/pkg/errors"
)
// AddColorToPalette adds c as the first color in p if not already there.
s = strings.TrimPrefix(s, "#")
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)
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/media"
- "github.com/pkg/errors"
+ "errors"
"github.com/bep/gowebp/libwebp/webpoptions"
if i.Cfg.Anchor != "" && i.Cfg.Anchor != smartCropIdentifier {
anchor, found := anchorPositions[i.Cfg.Anchor]
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
} else {
return c, errors.New("must provide Width or Height")
}
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 == "" {
"golang.org/x/image/bmp"
"golang.org/x/image/tiff"
+ "errors"
+
"github.com/gohugoio/hugo/common/hugio"
- "github.com/pkg/errors"
)
func NewImage(f Format, proc *ImageProcessor, img image.Image, s Spec) *Image {
})
if err != nil {
- return errors.Wrap(err, "failed to load image config")
+ return fmt.Errorf("failed to load image config: %w", err)
}
return nil
case "fit":
filters = append(filters, gift.ResizeToFit(conf.Width, conf.Height, conf.Filter))
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...)
"path/filepath"
"reflect"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/common/maps"
func Generate(c *codegen.Inspector) error {
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 {
- 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 {
- return errors.Wrap(err, "failed to generate file wrappers")
+ return fmt.Errorf("failed to generate file wrappers: %w", err)
}
return nil
package page
import (
+ "fmt"
"path/filepath"
"strings"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/hugofs/glob"
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
)
// A PageMatcher can be used to match a Page with Glob patterns.
}
}
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)
}
}
package page
import (
+ "fmt"
"sync"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/related"
- "github.com/pkg/errors"
"github.com/spf13/cast"
)
d, ok := p[0].(InternalDependencies)
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()
"strings"
"time"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/helpers"
)
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/source"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/common/maps"
var f hugio.ReadSeekCloser
f, err = fi.ReadSeekCloser()
if err != nil {
- err = errors.Wrap(err, "failed to open source file")
+ err = fmt.Errorf("failed to open source file: %w", err)
return
}
defer f.Close()
import (
"bufio"
"bytes"
+ "fmt"
"io"
"io/ioutil"
"mime"
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/resource"
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
)
type HTTPError struct {
func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resource, error) {
rURL, err := url.Parse(uri)
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)
_, httpResponse, err := c.cacheGetResource.GetOrCreate(resourceID, func() (io.ReadCloser, error) {
options, err := decodeRemoteOptions(optionsm)
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 {
return nil, err
req, err := http.NewRequest(options.Method, uri, options.BodyReader())
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)
if res.StatusCode != http.StatusNotFound {
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)
}
}
body, err := ioutil.ReadAll(res.Body)
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)
// Now resolve the media type primarily using the content.
mediaType := media.FromContent(c.rs.MediaTypes, extensionHints, body)
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
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources/resource"
- "github.com/pkg/errors"
"github.com/spf13/cast"
"github.com/gohugoio/hugo/common/maps"
glob, err := glob.GetGlob(srcKey)
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)
import (
"bytes"
+ "fmt"
"io"
"io/ioutil"
"os"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/resource"
- "github.com/pkg/errors"
)
// Options from https://babeljs.io/docs/en/options
configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile)
if configFile == "" && t.options.Config != "" {
// 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)
}
}
if hexec.IsNotFound(err) {
return herrors.ErrFeatureNotAvailable
}
- return errors.Wrap(err, errBuf.String())
+ return fmt.Errorf(errBuf.String()+": %w", err)
}
content, err := ioutil.ReadAll(compileOutput)
"crypto/sha512"
"encoding/base64"
"encoding/hex"
+ "fmt"
"hash"
"html/template"
"io"
"github.com/gohugoio/hugo/resources/internal"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/resource"
)
case "sha512":
return sha512.New(), nil
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)
}
}
"regexp"
"strings"
- "github.com/pkg/errors"
+ "errors"
"github.com/spf13/afero"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/common/herrors"
+ "github.com/gohugoio/hugo/common/text"
"github.com/gohugoio/hugo/hugolib/filesystems"
"github.com/gohugoio/hugo/media"
for i, ext := range opts.Inject {
impPath := filepath.FromSlash(ext)
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)
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
}
if err == nil {
- fe := herrors.NewFileError("js", 0, loc.Line, loc.Column, errors.New(msg.Text))
- err, _ := herrors.WithFileContext(fe, path, f, herrors.SimpleLineMatcher)
+ fe := herrors.NewFileError(path, errors.New(msg.Text)).
+ UpdatePosition(text.Position{Offset: -1, LineNumber: loc.Line, ColumnNumber: loc.Column}).
+ UpdateContent(f, herrors.SimpleLineMatcher)
+
f.Close()
- return err
+ return fe
}
return fmt.Errorf("%s", msg.Text)
"strings"
"github.com/gohugoio/hugo/common/maps"
- "github.com/pkg/errors"
"github.com/spf13/afero"
"github.com/evanw/esbuild/pkg/api"
func(args api.OnLoadArgs) (api.OnLoadResult, error) {
b, err := ioutil.ReadFile(args.Path)
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)
return api.OnLoadResult{
b, err := json.Marshal(params)
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)
paramsPlugin := api.Plugin{
"bytes"
"crypto/sha256"
"encoding/hex"
+ "fmt"
"io"
"io/ioutil"
"path"
"github.com/spf13/afero"
"github.com/spf13/cast"
+ "errors"
+
"github.com/gohugoio/hugo/hugofs"
- "github.com/pkg/errors"
"github.com/mitchellh/mapstructure"
configFile = t.rs.BaseFs.ResolveJSConfigFile(configFile)
if configFile == "" && t.options.Config != "" {
// 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)
}
}
if err != nil {
return inErr
}
- realFilename := fi.(hugofs.FileMetaInfo).Meta().Filename
-
- ferr := herrors.NewFileError("css", -1, file.Offset+1, 1, inErr)
- werr, ok := herrors.WithFileContextForFile(ferr, realFilename, file.Filename, imp.fs, herrors.SimpleLineMatcher)
+ realFilename := fi.(hugofs.FileMetaInfo).Meta().Filename
- if !ok {
- return ferr
- }
+ return herrors.NewFileErrorFromFile(inErr, file.Filename, realFilename, hugofs.Os, herrors.SimpleLineMatcher)
- return werr
}
package templates
import (
+ "fmt"
+
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/resources/internal"
"github.com/gohugoio/hugo/resources/resource"
"github.com/gohugoio/hugo/tpl"
- "github.com/pkg/errors"
)
// Client contains methods to perform template processing of Resource objects.
tplStr := helpers.ReaderToString(ctx.From)
templ, err := t.t.TextTmpl().Parse(ctx.InPath, tplStr)
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
return m.Offset+len(m.Line) >= start.Offset && strings.Contains(m.Line, context)
}
- ferr, ok := herrors.WithFileContextForFile(
- herrors.NewFileError("scss", -1, -1, start.Column, sassErr),
- filename,
- filename,
- hugofs.Os,
- offsetMatcher)
-
- if !ok {
- return sassErr
- }
+ return herrors.NewFileErrorFromFile(sassErr, filename, filename, hugofs.Os, offsetMatcher)
- return ferr
}
return err
}
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources"
- "github.com/pkg/errors"
)
// Used in tests. This feature requires Hugo to be built with the extended tag.
in := helpers.ReaderToString(src)
// 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
// that should cover many use cases, e.g. using SCSS as a preprocessor
// for Tailwind.
res, err = transpiler.Execute(in)
if err != nil {
- return res, errors.Wrap(err, "SCSS processing failed")
+ return res, fmt.Errorf("SCSS processing failed: %w", err)
}
out := res.CSS
"github.com/gohugoio/hugo/common/paths"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/resources/images"
"github.com/gohugoio/hugo/resources/images/exif"
"github.com/spf13/afero"
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
if err != nil {
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
updates.sourceFs = cache.fileCache.Fs
package source
import (
+ "fmt"
"path/filepath"
"strings"
"sync"
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/hugofs"
relPath := m.Path
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 == "" {
- 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)
package source
import (
+ "fmt"
"path/filepath"
"sync"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/hugofs"
)
f.filesInit.Do(func() {
err := f.captureFiles()
if err != nil {
- f.filesInitErr = errors.Wrap(err, "capture files")
+ f.filesInitErr = fmt.Errorf("capture files: %w", err)
}
})
return f.files, f.filesInitErr
"strings"
"time"
+ "errors"
+
"github.com/gohugoio/hugo/common/collections"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
- "github.com/pkg/errors"
"github.com/spf13/cast"
)
case reflect.Array:
slice = reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), 0, 0)
default:
- return nil, errors.Errorf("type %T not supported", seq)
+ return nil, fmt.Errorf("type %T not supported", seq)
}
seen := make(map[any]bool)
package collections
import (
+ "fmt"
"reflect"
"strings"
"github.com/gohugoio/hugo/common/hreflect"
"github.com/gohugoio/hugo/common/maps"
- "github.com/pkg/errors"
+ "errors"
)
// Merge creates a copy of the final parameter and merges the preceding
vdst, vsrc := reflect.ValueOf(dst), reflect.ValueOf(src)
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 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() {
- 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
"reflect"
"time"
+ "errors"
+
"github.com/mitchellh/hashstructure"
- "github.com/pkg/errors"
)
var (
case isNumber(kind):
return convertNumber(v, kind)
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)
}
}
import (
"fmt"
"reflect"
-
- "github.com/pkg/errors"
)
// SymDiff returns the symmetric difference of s1 and s2.
if ids1[key] != ids2[key] {
v, err := convertValue(ev, sliceElemType)
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)
}
"encoding/csv"
"encoding/json"
"errors"
+ "fmt"
"net/http"
"strings"
"github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/deps"
- _errors "github.com/pkg/errors"
)
// New returns a new instance of the data-namespaced template functions.
unmarshal := func(b []byte) (bool, error) {
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
}
var req *http.Request
req, err = http.NewRequest("GET", url, 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.
req, err := http.NewRequest("GET", url, 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) {
import (
"bytes"
+ "fmt"
"io/ioutil"
"net/http"
"net/url"
"path/filepath"
"time"
- "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/config"
res.Body.Close()
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)
"image"
"sync"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/resources/images"
"errors"
"fmt"
- _errors "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/resources"
)
m, err := maps.ToStringMapE(args[0])
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
"strconv"
"strings"
+ "errors"
+
"github.com/gohugoio/locales"
translators "github.com/gohugoio/localescompressed"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/common/hreflect"
"github.com/gohugoio/hugo/deps"
if len(args) > 0 {
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]
}
package openapi3
import (
+ "fmt"
"io/ioutil"
gyaml "github.com/ghodss/yaml"
- "github.com/pkg/errors"
+ "errors"
kopenapi3 "github.com/getkin/kin-openapi/openapi3"
"github.com/gohugoio/hugo/cache/namedmemcache"
v, err := ns.cache.GetOrCreate(key, func() (any, error) {
f := metadecoders.FormatFromMediaType(r.MediaType())
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()
"github.com/gohugoio/hugo/common/herrors"
+ "errors"
+
"github.com/gohugoio/hugo/common/maps"
- "github.com/pkg/errors"
"github.com/gohugoio/hugo/tpl/internal/resourcehelpers"
case *create.HTTPError:
return resources.NewErrorResource(resource.NewResourceError(v, v.Data))
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)))
}
}
case transpilerDart, transpilerLibSass:
transpiler = cast.ToString(t)
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)
}
}
}
import (
"errors"
+ "fmt"
"html/template"
"regexp"
"strings"
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
- _errors "github.com/pkg/errors"
"github.com/spf13/cast"
)
func (ns *Namespace) CountRunes(s any) (int, error) {
ss, err := cast.ToStringE(s)
if err != nil {
- return 0, _errors.Wrap(err, "Failed to convert content to string")
+ return 0, fmt.Errorf("Failed to convert content to string: %w", err)
}
counter := 0
func (ns *Namespace) RuneCount(s any) (int, error) {
ss, err := cast.ToStringE(s)
if err != nil {
- return 0, _errors.Wrap(err, "Failed to convert content to string")
+ return 0, fmt.Errorf("Failed to convert content to string: %w", err)
}
return utf8.RuneCountInString(ss), nil
}
func (ns *Namespace) CountWords(s any) (int, error) {
ss, err := cast.ToStringE(s)
if err != nil {
- return 0, _errors.Wrap(err, "Failed to convert content to string")
+ return 0, fmt.Errorf("Failed to convert content to string: %w", err)
}
isCJKLanguage, err := regexp.MatchString(`\p{Han}|\p{Hangul}|\p{Hiragana}|\p{Katakana}`, ss)
if err != nil {
- return 0, _errors.Wrap(err, "Failed to match regex pattern against string")
+ return 0, fmt.Errorf("Failed to match regex pattern against string: %w", err)
}
if !isCJKLanguage {
func (ns *Namespace) Count(substr, s any) (int, error) {
substrs, err := cast.ToStringE(substr)
if err != nil {
- return 0, _errors.Wrap(err, "Failed to convert substr to string")
+ return 0, fmt.Errorf("Failed to convert substr to string: %w", err)
}
ss, err := cast.ToStringE(s)
if err != nil {
- return 0, _errors.Wrap(err, "Failed to convert s to string")
+ return 0, fmt.Errorf("Failed to convert s to string: %w", err)
}
return strings.Count(ss, substrs), nil
}
--- /dev/null
+<!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;
+ color: #48b685;
+ 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" }}
+ {{ range $i, $e := .Files }}
+ {{ if not .ErrorContext }}
+ {{ continue }}
+ {{ end }}
+ {{ $params := printf "noclasses=true,style=paraiso-dark,linenos=table,hl_lines=%d,linenostart=%d" (add .ErrorContext.LinesPos 1) (sub .Position.LineNumber .ErrorContext.LinesPos) }}
+ {{ $lexer := .ErrorContext.ChromaLexer | default "go-html-template" }}
+ <h3><code>{{ path.Base .Position.Filename }}:</code></h3>
+ {{ highlight (delimit .ErrorContext.Lines "\n") $lexer $params }}
+ {{ end }}
+ <p class="version">{{ .Version }}</p>
+ <a href="">Reload Page</a>
+ </main>
+ </body>
+</html>
"bytes"
"context"
"embed"
+ "fmt"
"io"
"io/fs"
"os"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/hugofs/files"
- "github.com/pkg/errors"
htmltemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"
texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
}
defer f.Close()
- fe, ok := herrors.WithFileContext(inErr, info.realFilename, f, lineMatcher)
- if ok {
- return fe, true
- }
- return inErr, false
+ return herrors.NewFileError(info.realFilename, inErr).UpdateContent(f, lineMatcher), true
}
- inerr = errors.Wrap(inerr, "execute of template failed")
+ inerr = fmt.Errorf("execute of template failed: %w", inerr)
if err, ok := checkFilename(ts.info, inerr); ok {
return err
//go:embed embedded/templates/*
//go:embed embedded/templates/_default/*
+//go:embed embedded/templates/server/*
var embededTemplatesFs embed.FS
func (t *templateHandler) loadEmbedded() error {
name := strings.TrimPrefix(filepath.ToSlash(path), "embedded/templates/")
templateName := name
- // For the render hooks it does not make sense to preseve the
+ // For the render hooks and the server templates it does not make sense to preseve the
// double _indternal double book-keeping,
// just add it if its now provided by the user.
- if !strings.Contains(path, "_default/_markup") {
+ if !strings.Contains(path, "_default/_markup") && !strings.HasPrefix(name, "server/") {
templateName = internalPathPrefix + name
}
package tplimpl
import (
+ "fmt"
"regexp"
"strings"
"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"
+ "errors"
+
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/tpl"
"github.com/mitchellh/mapstructure"
- "github.com/pkg/errors"
)
type templateType int
}
if s, ok := cmd.Args[0].(*parse.StringNode); ok {
- errMsg := "failed to decode $_hugo_config in template"
+ errMsg := "failed to decode $_hugo_config in template: %w"
m, err := maps.ToStringMapE(s.Text)
if err != nil {
- c.err = errors.Wrap(err, errMsg)
+ c.err = fmt.Errorf(errMsg, err)
return
}
if err := mapstructure.WeakDecode(m, &c.t.parseInfo.Config); err != nil {
- c.err = errors.Wrap(err, errMsg)
+ c.err = fmt.Errorf(errMsg, err)
}
}
}
package tplimpl
import (
+ "fmt"
+
"github.com/gohugoio/hugo/common/herrors"
- "github.com/pkg/errors"
"github.com/spf13/afero"
)
}
func (info templateInfo) errWithFileContext(what string, err error) error {
- err = errors.Wrapf(err, what)
-
- err, _ = herrors.WithFileContextForFile(
- err,
- info.realFilename,
- info.filename,
- info.fs,
- herrors.SimpleLineMatcher)
+ err = fmt.Errorf(what+": %w", err)
+ fe := herrors.NewFileError(info.realFilename, err)
+ f, err := info.fs.Open(info.filename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ return fe.UpdateContent(f, herrors.SimpleLineMatcher)
- return err
}
"bytes"
"strings"
- "github.com/pkg/errors"
+ "errors"
"github.com/gohugoio/hugo/parser"
"github.com/gohugoio/hugo/parser/metadecoders"
package transform
import (
+ "fmt"
"io/ioutil"
"strings"
"github.com/mitchellh/mapstructure"
+ "errors"
+
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/parser/metadecoders"
- "github.com/pkg/errors"
"github.com/spf13/cast"
)
data = args[1]
decoder, err = decodeDecoder(m)
if err != nil {
- return nil, errors.WithMessage(err, "failed to decode options")
+ return nil, fmt.Errorf("failed to decode options: %w", err)
}
}
return ns.cache.GetOrCreate(key, func() (any, error) {
f := metadecoders.FormatFromMediaType(r.MediaType())
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()
dataStr, err := types.ToStringE(data)
if err != nil {
- return nil, errors.Errorf("type %T not supported", data)
+ return nil, fmt.Errorf("type %T not supported", data)
}
if dataStr == "" {
if i == 0 {
r = rr
} else {
- return 0, errors.Errorf("invalid character: %q", v)
+ return 0, fmt.Errorf("invalid character: %q", v)
}
}
"github.com/gohugoio/hugo/common/urls"
"github.com/gohugoio/hugo/deps"
- _errors "github.com/pkg/errors"
"github.com/spf13/cast"
)
func (ns *Namespace) Parse(rawurl any) (*url.URL, error) {
s, err := cast.ToStringE(rawurl)
if err != nil {
- return nil, _errors.Wrap(err, "Error in Parse")
+ return nil, fmt.Errorf("Error in Parse: %w", err)
}
return url.Parse(s)
import (
"bytes"
"io"
+ "io/ioutil"
bp "github.com/gohugoio/hugo/bufferpool"
+ "github.com/gohugoio/hugo/common/herrors"
+ "github.com/gohugoio/hugo/hugofs"
)
// Transformer is the func that needs to be implemented by a transformation step.
}
if err := tr(fb); err != nil {
- return err
+ // Write output to a temp file so it can be read by the user for trouble shooting.
+ filename := "output.html"
+ tempfile, ferr := ioutil.TempFile("", "hugo-transform-error")
+ if ferr == nil {
+ filename = tempfile.Name()
+ defer tempfile.Close()
+ _, _ = io.Copy(tempfile, fb.from)
+ return herrors.NewFileErrorFromFile(err, filename, filename, hugofs.Os, nil)
+ }
+ return herrors.NewFileError(filename, err).UpdateContent(fb.from, nil)
+
}
}