Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resources: Replace error handling in GetRemote with try (note) #13217

Merged
merged 1 commit into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading