diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-05-02 16:07:52 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-05-06 19:43:22 +0200 |
commit | f2946da9e806c2bafbdd26707fe339db79bd980b (patch) | |
tree | b5609317a861ea5f399e094e1b9287ca71dc22d1 /hugolib | |
parent | 6eea32bd6bc8e7a7dd07a8cb6a8343ae2c74aba0 (diff) |
Improve error messages, esp. when the server is running
* Add file context to minifier errors when publishing
* Misc fixes (see issues)
* Allow custom server error template in layouts/server/error.html
To get to this, this commit also cleans up and simplifies the code surrounding errors and files. This also removes the usage of `github.com/pkg/errors`, mostly because of https://github.com/pkg/errors/issues/223 -- but also because most of this is now built-in to Go.
Fixes #9852
Fixes #9857
Fixes #9863
Diffstat (limited to 'hugolib')
-rw-r--r-- | hugolib/config.go | 5 | ||||
-rw-r--r-- | hugolib/configdir_test.go | 2 | ||||
-rw-r--r-- | hugolib/content_factory.go | 10 | ||||
-rw-r--r-- | hugolib/content_map.go | 3 | ||||
-rw-r--r-- | hugolib/content_map_page.go | 7 | ||||
-rw-r--r-- | hugolib/fileInfo.go | 5 | ||||
-rw-r--r-- | hugolib/filesystems/basefs.go | 10 | ||||
-rw-r--r-- | hugolib/hugo_sites.go | 39 | ||||
-rw-r--r-- | hugolib/hugo_sites_build.go | 10 | ||||
-rw-r--r-- | hugolib/hugo_sites_build_errors_test.go | 108 | ||||
-rw-r--r-- | hugolib/integrationtest_builder.go | 3 | ||||
-rw-r--r-- | hugolib/page.go | 78 | ||||
-rw-r--r-- | hugolib/page__meta.go | 3 | ||||
-rw-r--r-- | hugolib/page__per_output.go | 7 | ||||
-rw-r--r-- | hugolib/page__ref.go | 5 | ||||
-rw-r--r-- | hugolib/page_unwrap.go | 4 | ||||
-rw-r--r-- | hugolib/pages_process.go | 3 | ||||
-rw-r--r-- | hugolib/paths/paths.go | 3 | ||||
-rw-r--r-- | hugolib/shortcode.go | 31 | ||||
-rw-r--r-- | hugolib/shortcode_test.go | 4 | ||||
-rw-r--r-- | hugolib/site.go | 14 | ||||
-rw-r--r-- | hugolib/site_render.go | 5 | ||||
-rw-r--r-- | hugolib/testhelpers_test.go | 10 |
23 files changed, 226 insertions, 143 deletions
diff --git a/hugolib/config.go b/hugolib/config.go index 5d2c6ddf7..b2713758a 100644 --- a/hugolib/config.go +++ b/hugolib/config.go @@ -33,11 +33,12 @@ import ( "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" @@ -510,5 +511,5 @@ func (configLoader) loadSiteConfig(cfg config.Provider) (scfg SiteConfig, err er } 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) } diff --git a/hugolib/configdir_test.go b/hugolib/configdir_test.go index 998010318..7ac3f969d 100644 --- a/hugolib/configdir_test.go +++ b/hugolib/configdir_test.go @@ -146,7 +146,7 @@ baseURL = "https://example.org" _, _, 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")) } diff --git a/hugolib/content_factory.go b/hugolib/content_factory.go index bea98894d..e6e82979f 100644 --- a/hugolib/content_factory.go +++ b/hugolib/content_factory.go @@ -14,6 +14,7 @@ package hugolib import ( + "fmt" "io" "path/filepath" "strings" @@ -25,7 +26,6 @@ import ( "github.com/gohugoio/hugo/resources/page" - "github.com/pkg/errors" "github.com/spf13/afero" ) @@ -48,12 +48,12 @@ func (f ContentFactory) ApplyArchetypeFilename(w io.Writer, p page.Page, archety } 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) } @@ -79,12 +79,12 @@ func (f ContentFactory) ApplyArchetypeTemplate(w io.Writer, p page.Page, archety templ, err := ps.s.TextTmpl().Parse("archetype.md", string(templateSource)) 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)) diff --git a/hugolib/content_map.go b/hugolib/content_map.go index 330391dcb..6849998b6 100644 --- a/hugolib/content_map.go +++ b/hugolib/content_map.go @@ -23,7 +23,6 @@ import ( "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources/page" - "github.com/pkg/errors" "github.com/gohugoio/hugo/hugofs/files" @@ -207,7 +206,7 @@ func (b *cmInsertKeyBuilder) WithFile(fi hugofs.FileMetaInfo) *cmInsertKeyBuilde 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 } diff --git a/hugolib/content_map_page.go b/hugolib/content_map_page.go index 21a4e8f2a..a16e4720d 100644 --- a/hugolib/content_map_page.go +++ b/hugolib/content_map_page.go @@ -35,7 +35,6 @@ import ( "github.com/spf13/cast" "github.com/gohugoio/hugo/common/para" - "github.com/pkg/errors" ) func newPageMaps(h *HugoSites) *pageMaps { @@ -131,13 +130,13 @@ func (m *pageMap) newPageFromContentNode(n *contentNode, parentBucket *pagesMapB 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 @@ -282,7 +281,7 @@ func (m *pageMap) createSiteTaxonomies() error { } 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 { diff --git a/hugolib/fileInfo.go b/hugolib/fileInfo.go index fdfd34b16..1cdd7041d 100644 --- a/hugolib/fileInfo.go +++ b/hugolib/fileInfo.go @@ -14,12 +14,11 @@ package hugolib import ( + "fmt" "strings" "github.com/gohugoio/hugo/hugofs/files" - "github.com/pkg/errors" - "github.com/gohugoio/hugo/hugofs" "github.com/spf13/afero" @@ -41,7 +40,7 @@ type fileInfo struct { 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 diff --git a/hugolib/filesystems/basefs.go b/hugolib/filesystems/basefs.go index d02f8c624..2447246d6 100644 --- a/hugolib/filesystems/basefs.go +++ b/hugolib/filesystems/basefs.go @@ -35,8 +35,6 @@ import ( "github.com/gohugoio/hugo/hugofs/files" - "github.com/pkg/errors" - "github.com/gohugoio/hugo/modules" hpaths "github.com/gohugoio/hugo/common/paths" @@ -176,7 +174,7 @@ func (b *BaseFs) AbsProjectContentDir(filename string) (string, string, error) { } - return "", "", errors.Errorf("could not determine content directory for %q", filename) + return "", "", fmt.Errorf("could not determine content directory for %q", filename) } // ResolveJSConfigFile resolves the JS-related config file to a absolute @@ -468,7 +466,7 @@ func NewBase(p *paths.Paths, logger loggers.Logger, options ...func(*BaseFs) err 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 @@ -502,7 +500,7 @@ func (b *sourceFilesystemsBuilder) Build() (*SourceFilesystems, error) { 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 @@ -544,7 +542,7 @@ func (b *sourceFilesystemsBuilder) Build() (*SourceFilesystems, error) { 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) diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go index d67652dab..e0d69a8af 100644 --- a/hugolib/hugo_sites.go +++ b/hugolib/hugo_sites.go @@ -15,6 +15,7 @@ package hugolib import ( "context" + "fmt" "io" "path/filepath" "sort" @@ -33,9 +34,10 @@ import ( "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" @@ -194,7 +196,7 @@ func (h *hugoSitesInit) Reset() { 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 @@ -242,7 +244,7 @@ func (h *HugoSites) pickOneAndLogTheRest(errors []error) error { 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 } @@ -327,7 +329,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) { 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 @@ -365,7 +367,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) { 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 }) @@ -391,7 +393,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) { 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 }) @@ -402,7 +404,7 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) { 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 @@ -485,7 +487,7 @@ func (l configLoader) applyDeps(cfg deps.DepsCfg, sites ...*Site) error { 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 @@ -516,17 +518,17 @@ func (l configLoader) applyDeps(cfg deps.DepsCfg, sites ...*Site) error { 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 { @@ -548,7 +550,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) { } 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...) } @@ -882,7 +884,7 @@ func (h *HugoSites) handleDataFile(r source.File) error { 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() @@ -960,23 +962,16 @@ func (h *HugoSites) errWithFileContext(err error, f source.File) error { 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) diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go index 4616b6dbb..1a191257c 100644 --- a/hugolib/hugo_sites_build.go +++ b/hugolib/hugo_sites_build.go @@ -35,7 +35,7 @@ import ( "github.com/gohugoio/hugo/output" - "github.com/pkg/errors" + "errors" "github.com/fsnotify/fsnotify" "github.com/gohugoio/hugo/helpers" @@ -50,7 +50,7 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error { 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() } @@ -99,11 +99,11 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error { 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) } } @@ -117,7 +117,7 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error { } trace.WithRegion(ctx, "process", f) if err != nil { - return errors.Wrap(err, "process") + return fmt.Errorf("process: %w", err) } f = func() { diff --git a/hugolib/hugo_sites_build_errors_test.go b/hugolib/hugo_sites_build_errors_test.go index 8b23e7ac7..8f983075d 100644 --- a/hugolib/hugo_sites_build_errors_test.go +++ b/hugolib/hugo_sites_build_errors_test.go @@ -2,6 +2,7 @@ package hugolib import ( "fmt" + "os" "path/filepath" "strings" "testing" @@ -17,14 +18,15 @@ type testSiteBuildErrorAsserter struct { 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())) } @@ -87,7 +89,6 @@ func TestSiteBuildErrors(t *testing.T) { 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()) }, }, @@ -101,7 +102,6 @@ func TestSiteBuildErrors(t *testing.T) { 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()) }, }, @@ -115,7 +115,6 @@ func TestSiteBuildErrors(t *testing.T) { 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()) }, }, @@ -130,18 +129,17 @@ func TestSiteBuildErrors(t *testing.T) { }, }, { - 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) + }, }, { @@ -154,7 +152,6 @@ func TestSiteBuildErrors(t *testing.T) { 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()) }, }, @@ -162,10 +159,14 @@ func TestSiteBuildErrors(t *testing.T) { 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) }, }, { @@ -177,7 +178,6 @@ func TestSiteBuildErrors(t *testing.T) { 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") }, }, { @@ -188,9 +188,7 @@ func TestSiteBuildErrors(t *testing.T) { }, 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") }, }, { @@ -211,6 +209,9 @@ func TestSiteBuildErrors(t *testing.T) { } for _, test := range tests { + if test.name != "Invalid JSON front matter" { + continue + } test := test t.Run(test.name, func(t *testing.T) { t.Parallel() @@ -311,6 +312,77 @@ Some content. } }) } + +} + +// Issue 9852 +func TestErrorMinify(t *testing.T) { + t.Parallel() + + files := ` +-- config.toml -- +minify = true + +-- layouts/index.html -- +<body> +<script>=;</script> +</body> + +` + + b, err := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).BuildE() + + fe := herrors.UnwrapFileError(err) + b.Assert(fe, qt.IsNotNil) + b.Assert(fe.Position().LineNumber, qt.Equals, 2) + b.Assert(fe.Position().ColumnNumber, qt.Equals, 9) + b.Assert(fe.Error(), qt.Contains, "unexpected = in expression on line 2 and column 9") + b.Assert(filepath.ToSlash(fe.Position().Filename), qt.Contains, "hugo-transform-error") + b.Assert(os.Remove(fe.Position().Filename), qt.IsNil) + +} + +func TestErrorNested(t *testing.T) { + t.Parallel() + + files := ` +-- config.toml -- +-- layouts/index.html -- +line 1 +12{{ partial "foo.html" . }} +line 4 +line 5 +-- layouts/partials/foo.html -- +line 1 +line 2 +123{{ .ThisDoesNotExist }} +line 4 +` + + b, err := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).BuildE() + + b.Assert(err, qt.IsNotNil) + errors := herrors.UnwrapFileErrorsWithErrorContext(err) + b.Assert(errors, qt.HasLen, 2) + fmt.Println(errors[0]) + b.Assert(errors[0].Position().LineNumber, qt.Equals, 2) + b.Assert(errors[0].Position().ColumnNumber, qt.Equals, 5) + b.Assert(errors[0].Error(), qt.Contains, filepath.FromSlash(`"/layouts/index.html:2:5": execute of template failed`)) + b.Assert(errors[0].ErrorContext().Lines, qt.DeepEquals, []string{"line 1", "12{{ partial \"foo.html\" . }}", "line 4", "line 5"}) + b.Assert(errors[1].Position().LineNumber, qt.Equals, 3) + b.Assert(errors[1].Position().ColumnNumber, qt.Equals, 6) + b.Assert(errors[1].ErrorContext().Lines, qt.DeepEquals, []string{"line 1", "line 2", "123{{ .ThisDoesNotExist }}", "line 4"}) + } // https://github.com/gohugoio/hugo/issues/5375 diff --git a/hugolib/integrationtest_builder.go b/hugolib/integrationtest_builder.go index 58e751892..c3fb9fffc 100644 --- a/hugolib/integrationtest_builder.go +++ b/hugolib/integrationtest_builder.go @@ -169,8 +169,7 @@ func (s *IntegrationTestBuilder) destinationExists(filename string) bool { } 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) { diff --git a/hugolib/page.go b/hugolib/page.go index 77165c072..4faefa3cc 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -39,8 +39,9 @@ import ( "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" @@ -482,7 +483,7 @@ func (p *pageState) renderResources() (err error) { 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 } @@ -560,23 +561,37 @@ func (p *pageState) addDependency(dep identity.Provider) { // 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 |