Skip to content

Commit

Permalink
resources: Replace error handling in GetRemote with try (note)
Browse files Browse the repository at this point in the history
Closes #13216
  • Loading branch information
bep committed Jan 6, 2025
1 parent 4ea94c4 commit 0918e08
Show file tree
Hide file tree
Showing 16 changed files with 108 additions and 223 deletions.
23 changes: 21 additions & 2 deletions common/herrors/file_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,16 +258,35 @@ func openFile(filename string, fs afero.Fs) (afero.File, string, error) {
return f, realFilename, nil
}

// Cause returns the underlying error or itself if it does not implement Unwrap.
// Cause returns the underlying error, that is,
// it unwraps errors until it finds one that does not implement
// the Unwrap method.
// For a shallow variant, see Unwrap.
func Cause(err error) error {
type unwrapper interface {
Unwrap() error
}

for err != nil {
cause, ok := err.(unwrapper)
if !ok {
break
}
err = cause.Unwrap()
}
return err
}

// Unwrap returns the underlying error or itself if it does not implement Unwrap.
func Unwrap(err error) error {
if u := errors.Unwrap(err); u != nil {
return u
}
return err
}

func extractFileTypePos(err error) (string, text.Position) {
err = Cause(err)
err = Unwrap(err)

var fileType string

Expand Down
14 changes: 13 additions & 1 deletion hugolib/hugo_sites_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,18 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {

siteRenderContext := &siteRenderContext{cfg: config, multihost: h.Configs.IsMultihost}

renderErr := func(err error) error {
if err == nil {
return nil
}
if strings.Contains(err.Error(), "can't evaluate field Err in type resource.Resource") {
// In Hugo 0.141.0 we replaced the special error handling for resources.GetRemote
// with the more general try.
return fmt.Errorf("%s: Resource.Err was removed in Hugo v0.141.0 and replaced with a new try keyword, see https://gohugo.io/functions/go-template/try/", err)
}
return err
}

i := 0
for _, s := range h.Sites {
segmentFilter := s.conf.C.SegmentFilter
Expand Down Expand Up @@ -390,7 +402,7 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
}
} else {
if err := s.render(siteRenderContext); err != nil {
return err
return renderErr(err)
}
}
loggers.TimeTrackf(ll, start, nil, "")
Expand Down
4 changes: 0 additions & 4 deletions hugolib/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,6 @@ func (p *pageState) isContentNodeBranch() bool {
return p.IsNode()
}

func (p *pageState) Err() resource.ResourceError {
return nil
}

// Eq returns whether the current page equals the given page.
// This is what's invoked when doing `{{ if eq $page $otherPage }}`
func (p *pageState) Eq(other any) bool {
Expand Down
14 changes: 7 additions & 7 deletions hugolib/resource_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,22 @@ FIT: {{ $fit.Name }}|{{ $fit.RelPermalink }}|{{ $fit.Width }}
CSS integrity Data first: {{ $cssFingerprinted1.Data.Integrity }} {{ $cssFingerprinted1.RelPermalink }}
CSS integrity Data last: {{ $cssFingerprinted2.RelPermalink }} {{ $cssFingerprinted2.Data.Integrity }}
{{ $failedImg := resources.GetRemote "%[1]s/fail.jpg" }}
{{ $failedImg := try (resources.GetRemote "%[1]s/fail.jpg") }}
{{ $rimg := resources.GetRemote "%[1]s/sunset.jpg" }}
{{ $remotenotfound := resources.GetRemote "%[1]s/notfound.jpg" }}
{{ $localnotfound := resources.Get "images/notfound.jpg" }}
{{ $gopherprotocol := resources.GetRemote "gopher://example.org" }}
{{ $gopherprotocol := try (resources.GetRemote "gopher://example.org") }}
{{ $rfit := $rimg.Fit "200x200" }}
{{ $rfit2 := $rfit.Fit "100x200" }}
{{ $rimg = $rimg | fingerprint }}
SUNSET REMOTE: {{ $rimg.Name }}|{{ $rimg.RelPermalink }}|{{ $rimg.Width }}|{{ len $rimg.Content }}
FIT REMOTE: {{ $rfit.Name }}|{{ $rfit.RelPermalink }}|{{ $rfit.Width }}
REMOTE NOT FOUND: {{ if $remotenotfound }}FAILED{{ else}}OK{{ end }}
LOCAL NOT FOUND: {{ if $localnotfound }}FAILED{{ else}}OK{{ end }}
PRINT PROTOCOL ERROR1: {{ with $gopherprotocol }}{{ . | safeHTML }}{{ end }}
PRINT PROTOCOL ERROR1: {{ with $gopherprotocol }}{{ .Value | safeHTML }}{{ end }}
PRINT PROTOCOL ERROR2: {{ with $gopherprotocol }}{{ .Err | safeHTML }}{{ end }}
PRINT PROTOCOL ERROR DETAILS: {{ with $gopherprotocol }}Err: {{ .Err | safeHTML }}{{ with .Err }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}{{ end }}|{{ end }}{{ end }}
FAILED REMOTE ERROR DETAILS CONTENT: {{ with $failedImg.Err }}|{{ . }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}|ContentLength: {{ .ContentLength }}|ContentType: {{ .ContentType }}{{ end }}{{ end }}|
PRINT PROTOCOL ERROR DETAILS: {{ with $gopherprotocol }}{{ with .Err }}Err: {{ . | safeHTML }}{{ with .Cause }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}{{ end }}|{{ end }}{{ end }}{{ end }}
FAILED REMOTE ERROR DETAILS CONTENT: {{ with $failedImg }}{{ with .Err }}{{ with .Cause }}{{ . }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}|ContentLength: {{ .ContentLength }}|ContentType: {{ .ContentType }}{{ end }}{{ end }}{{ end }}{{ end }}|
`, ts.URL))

fs := b.Fs.Source
Expand Down Expand Up @@ -114,8 +114,8 @@ SUNSET REMOTE: /sunset_%[1]s.jpg|/sunset_%[1]s.a9bf1d944e19c0f382e0d8f51de690f7d
FIT REMOTE: /sunset_%[1]s.jpg|/sunset_%[1]s_hu15210517121918042184.jpg|200
REMOTE NOT FOUND: OK
LOCAL NOT FOUND: OK
PRINT PROTOCOL ERROR DETAILS: Err: error calling resources.GetRemote: Get "gopher://example.org": unsupported protocol scheme "gopher"||
FAILED REMOTE ERROR DETAILS CONTENT: |failed to fetch remote resource from '%[2]s/fail.jpg': Not Implemented|Body: { msg: failed }
PRINT PROTOCOL ERROR DETAILS: Err: template: index.html:22:36: executing "index.html" at <resources.GetRemote>: error calling GetRemote: Get "gopher://example.org": unsupported protocol scheme "gopher"|
FAILED REMOTE ERROR DETAILS CONTENT: failed to fetch remote resource from &#39;%[2]s/fail.jpg&#39;: Not Implemented|Body: { msg: failed }
|StatusCode: 501|ContentLength: 16|ContentType: text/plain; charset=utf-8|
Expand Down
145 changes: 0 additions & 145 deletions resources/errorResource.go

This file was deleted.

4 changes: 0 additions & 4 deletions resources/page/page_nop.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ type nopPage int

var noOpPathInfo = media.DefaultPathParser.Parse(files.ComponentFolderContent, "no-op.md")

func (p *nopPage) Err() resource.ResourceError {
return nil
}

func (p *nopPage) Aliases() []string {
return nil
}
Expand Down
4 changes: 0 additions & 4 deletions resources/page/testhelpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,6 @@ type testPage struct {
sectionEntries []string
}

func (p *testPage) Err() resource.ResourceError {
return nil
}

func (p *testPage) Aliases() []string {
panic("testpage: not implemented")
}
Expand Down
7 changes: 0 additions & 7 deletions resources/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,6 @@ type resourceCopier interface {

// Copy copies r to the targetPath given.
func Copy(r resource.Resource, targetPath string) resource.Resource {
if r.Err() != nil {
panic(fmt.Sprintf("Resource has an .Err: %s", r.Err()))
}
return r.(resourceCopier).cloneTo(targetPath)
}

Expand Down Expand Up @@ -439,10 +436,6 @@ func (l *genericResource) Content(context.Context) (any, error) {
return hugio.ReadString(r)
}

func (r *genericResource) Err() resource.ResourceError {
return nil
}

func (l *genericResource) Data() any {
return l.sd.Data
}
Expand Down
11 changes: 3 additions & 8 deletions resources/resource/resourcetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ type OriginProvider interface {

// NewResourceError creates a new ResourceError.
func NewResourceError(err error, data any) ResourceError {
if data == nil {
data = map[string]any{}
}
return &resourceError{
error: err,
data: data,
Expand All @@ -65,13 +68,6 @@ type ResourceError interface {
ResourceDataProvider
}

// ErrProvider provides an Err.
type ErrProvider interface {
// Err returns an error if this resource is in an error state.
// This will currently only be set for resources obtained from resources.GetRemote.
Err() ResourceError
}

// Resource represents a linkable resource, i.e. a content page, image etc.
type Resource interface {
ResourceWithoutMeta
Expand All @@ -83,7 +79,6 @@ type ResourceWithoutMeta interface {
MediaTypeProvider
ResourceLinksProvider
ResourceDataProvider
ErrProvider
}

type ResourceWrapper interface {
Expand Down
20 changes: 10 additions & 10 deletions resources/resource_factories/create/create_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,17 @@ func TestGetRemoteHead(t *testing.T) {
[security.http]
methods = ['(?i)GET|POST|HEAD']
urls = ['.*gohugo\.io.*']
-- layouts/index.html --
{{ $url := "https://gohugo.io/img/hugo.png" }}
{{ $opts := dict "method" "head" }}
{{ with resources.GetRemote $url $opts }}
{{ with try (resources.GetRemote $url $opts) }}
{{ with .Err }}
{{ errorf "Unable to get remote resource: %s" . }}
{{ else }}
{{ else with .Value }}
Head Content: {{ .Content }}. Head Data: {{ .Data }}
{{ end }}
{{ else }}
{{ else }}
{{ errorf "Unable to get remote resource: %s" $url }}
{{ end }}
{{ end }}
`

Expand Down Expand Up @@ -90,14 +89,15 @@ mediaTypes = ['text/plain']
-- layouts/_default/single.html --
{{ $url := printf "%s%s" "URL" .RelPermalink}}
{{ $opts := dict }}
{{ with resources.GetRemote $url $opts }}
{{ with try (resources.GetRemote $url $opts) }}
{{ with .Err }}
{{ errorf "Got Err: %s. Data: %v" . .Data }}
{{ else }}
{{ errorf "Got Err: %s" . }}
{{ with .Cause }}{{ errorf "Data: %s" .Data }}{{ end }}
{{ else with .Value }}
Content: {{ .Content }}
{{ else }}
{{ errorf "Unable to get remote resource: %s" $url }}
{{ end }}
{{ else }}
{{ errorf "Unable to get remote resource: %s" $url }}
{{ end }}
`

Expand Down
4 changes: 0 additions & 4 deletions resources/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,6 @@ func (r *resourceAdapter) Content(ctx context.Context) (any, error) {
return r.target.Content(ctx)
}

func (r *resourceAdapter) Err() resource.ResourceError {
return nil
}

func (r *resourceAdapter) GetIdentity() identity.Identity {
return identity.FirstIdentity(r.target)
}
Expand Down
Loading

0 comments on commit 0918e08

Please sign in to comment.