Skip to content

Commit 0918e08

Browse files
committed
resources: Replace error handling in GetRemote with try (note)
Closes #13216
1 parent 4ea94c4 commit 0918e08

File tree

16 files changed

+108
-223
lines changed

16 files changed

+108
-223
lines changed

common/herrors/file_error.go

+21-2
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,35 @@ func openFile(filename string, fs afero.Fs) (afero.File, string, error) {
258258
return f, realFilename, nil
259259
}
260260

261-
// Cause returns the underlying error or itself if it does not implement Unwrap.
261+
// Cause returns the underlying error, that is,
262+
// it unwraps errors until it finds one that does not implement
263+
// the Unwrap method.
264+
// For a shallow variant, see Unwrap.
262265
func Cause(err error) error {
266+
type unwrapper interface {
267+
Unwrap() error
268+
}
269+
270+
for err != nil {
271+
cause, ok := err.(unwrapper)
272+
if !ok {
273+
break
274+
}
275+
err = cause.Unwrap()
276+
}
277+
return err
278+
}
279+
280+
// Unwrap returns the underlying error or itself if it does not implement Unwrap.
281+
func Unwrap(err error) error {
263282
if u := errors.Unwrap(err); u != nil {
264283
return u
265284
}
266285
return err
267286
}
268287

269288
func extractFileTypePos(err error) (string, text.Position) {
270-
err = Cause(err)
289+
err = Unwrap(err)
271290

272291
var fileType string
273292

hugolib/hugo_sites_build.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,18 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
343343

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

346+
renderErr := func(err error) error {
347+
if err == nil {
348+
return nil
349+
}
350+
if strings.Contains(err.Error(), "can't evaluate field Err in type resource.Resource") {
351+
// In Hugo 0.141.0 we replaced the special error handling for resources.GetRemote
352+
// with the more general try.
353+
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)
354+
}
355+
return err
356+
}
357+
346358
i := 0
347359
for _, s := range h.Sites {
348360
segmentFilter := s.conf.C.SegmentFilter
@@ -390,7 +402,7 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
390402
}
391403
} else {
392404
if err := s.render(siteRenderContext); err != nil {
393-
return err
405+
return renderErr(err)
394406
}
395407
}
396408
loggers.TimeTrackf(ll, start, nil, "")

hugolib/page.go

-4
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,6 @@ func (p *pageState) isContentNodeBranch() bool {
185185
return p.IsNode()
186186
}
187187

188-
func (p *pageState) Err() resource.ResourceError {
189-
return nil
190-
}
191-
192188
// Eq returns whether the current page equals the given page.
193189
// This is what's invoked when doing `{{ if eq $page $otherPage }}`
194190
func (p *pageState) Eq(other any) bool {

hugolib/resource_chain_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,22 @@ FIT: {{ $fit.Name }}|{{ $fit.RelPermalink }}|{{ $fit.Width }}
6767
CSS integrity Data first: {{ $cssFingerprinted1.Data.Integrity }} {{ $cssFingerprinted1.RelPermalink }}
6868
CSS integrity Data last: {{ $cssFingerprinted2.RelPermalink }} {{ $cssFingerprinted2.Data.Integrity }}
6969
70-
{{ $failedImg := resources.GetRemote "%[1]s/fail.jpg" }}
70+
{{ $failedImg := try (resources.GetRemote "%[1]s/fail.jpg") }}
7171
{{ $rimg := resources.GetRemote "%[1]s/sunset.jpg" }}
7272
{{ $remotenotfound := resources.GetRemote "%[1]s/notfound.jpg" }}
7373
{{ $localnotfound := resources.Get "images/notfound.jpg" }}
74-
{{ $gopherprotocol := resources.GetRemote "gopher://example.org" }}
74+
{{ $gopherprotocol := try (resources.GetRemote "gopher://example.org") }}
7575
{{ $rfit := $rimg.Fit "200x200" }}
7676
{{ $rfit2 := $rfit.Fit "100x200" }}
7777
{{ $rimg = $rimg | fingerprint }}
7878
SUNSET REMOTE: {{ $rimg.Name }}|{{ $rimg.RelPermalink }}|{{ $rimg.Width }}|{{ len $rimg.Content }}
7979
FIT REMOTE: {{ $rfit.Name }}|{{ $rfit.RelPermalink }}|{{ $rfit.Width }}
8080
REMOTE NOT FOUND: {{ if $remotenotfound }}FAILED{{ else}}OK{{ end }}
8181
LOCAL NOT FOUND: {{ if $localnotfound }}FAILED{{ else}}OK{{ end }}
82-
PRINT PROTOCOL ERROR1: {{ with $gopherprotocol }}{{ . | safeHTML }}{{ end }}
82+
PRINT PROTOCOL ERROR1: {{ with $gopherprotocol }}{{ .Value | safeHTML }}{{ end }}
8383
PRINT PROTOCOL ERROR2: {{ with $gopherprotocol }}{{ .Err | safeHTML }}{{ end }}
84-
PRINT PROTOCOL ERROR DETAILS: {{ with $gopherprotocol }}Err: {{ .Err | safeHTML }}{{ with .Err }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}{{ end }}|{{ end }}{{ end }}
85-
FAILED REMOTE ERROR DETAILS CONTENT: {{ with $failedImg.Err }}|{{ . }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}|ContentLength: {{ .ContentLength }}|ContentType: {{ .ContentType }}{{ end }}{{ end }}|
84+
PRINT PROTOCOL ERROR DETAILS: {{ with $gopherprotocol }}{{ with .Err }}Err: {{ . | safeHTML }}{{ with .Cause }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}{{ end }}|{{ end }}{{ end }}{{ end }}
85+
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 }}|
8686
`, ts.URL))
8787

8888
fs := b.Fs.Source
@@ -114,8 +114,8 @@ SUNSET REMOTE: /sunset_%[1]s.jpg|/sunset_%[1]s.a9bf1d944e19c0f382e0d8f51de690f7d
114114
FIT REMOTE: /sunset_%[1]s.jpg|/sunset_%[1]s_hu15210517121918042184.jpg|200
115115
REMOTE NOT FOUND: OK
116116
LOCAL NOT FOUND: OK
117-
PRINT PROTOCOL ERROR DETAILS: Err: error calling resources.GetRemote: Get "gopher://example.org": unsupported protocol scheme "gopher"||
118-
FAILED REMOTE ERROR DETAILS CONTENT: |failed to fetch remote resource from '%[2]s/fail.jpg': Not Implemented|Body: { msg: failed }
117+
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"|
118+
FAILED REMOTE ERROR DETAILS CONTENT: failed to fetch remote resource from &#39;%[2]s/fail.jpg&#39;: Not Implemented|Body: { msg: failed }
119119
|StatusCode: 501|ContentLength: 16|ContentType: text/plain; charset=utf-8|
120120
121121

resources/errorResource.go

-145
This file was deleted.

resources/page/page_nop.go

-4
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ type nopPage int
6161

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

64-
func (p *nopPage) Err() resource.ResourceError {
65-
return nil
66-
}
67-
6864
func (p *nopPage) Aliases() []string {
6965
return nil
7066
}

resources/page/testhelpers_test.go

-4
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ type testPage struct {
111111
sectionEntries []string
112112
}
113113

114-
func (p *testPage) Err() resource.ResourceError {
115-
return nil
116-
}
117-
118114
func (p *testPage) Aliases() []string {
119115
panic("testpage: not implemented")
120116
}

resources/resource.go

-7
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,6 @@ type resourceCopier interface {
224224

225225
// Copy copies r to the targetPath given.
226226
func Copy(r resource.Resource, targetPath string) resource.Resource {
227-
if r.Err() != nil {
228-
panic(fmt.Sprintf("Resource has an .Err: %s", r.Err()))
229-
}
230227
return r.(resourceCopier).cloneTo(targetPath)
231228
}
232229

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

442-
func (r *genericResource) Err() resource.ResourceError {
443-
return nil
444-
}
445-
446439
func (l *genericResource) Data() any {
447440
return l.sd.Data
448441
}

resources/resource/resourcetypes.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ type OriginProvider interface {
4343

4444
// NewResourceError creates a new ResourceError.
4545
func NewResourceError(err error, data any) ResourceError {
46+
if data == nil {
47+
data = map[string]any{}
48+
}
4649
return &resourceError{
4750
error: err,
4851
data: data,
@@ -65,13 +68,6 @@ type ResourceError interface {
6568
ResourceDataProvider
6669
}
6770

68-
// ErrProvider provides an Err.
69-
type ErrProvider interface {
70-
// Err returns an error if this resource is in an error state.
71-
// This will currently only be set for resources obtained from resources.GetRemote.
72-
Err() ResourceError
73-
}
74-
7571
// Resource represents a linkable resource, i.e. a content page, image etc.
7672
type Resource interface {
7773
ResourceWithoutMeta
@@ -83,7 +79,6 @@ type ResourceWithoutMeta interface {
8379
MediaTypeProvider
8480
ResourceLinksProvider
8581
ResourceDataProvider
86-
ErrProvider
8782
}
8883

8984
type ResourceWrapper interface {

resources/resource_factories/create/create_integration_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,17 @@ func TestGetRemoteHead(t *testing.T) {
3131
[security.http]
3232
methods = ['(?i)GET|POST|HEAD']
3333
urls = ['.*gohugo\.io.*']
34-
3534
-- layouts/index.html --
3635
{{ $url := "https://gohugo.io/img/hugo.png" }}
3736
{{ $opts := dict "method" "head" }}
38-
{{ with resources.GetRemote $url $opts }}
37+
{{ with try (resources.GetRemote $url $opts) }}
3938
{{ with .Err }}
4039
{{ errorf "Unable to get remote resource: %s" . }}
41-
{{ else }}
40+
{{ else with .Value }}
4241
Head Content: {{ .Content }}. Head Data: {{ .Data }}
43-
{{ end }}
44-
{{ else }}
42+
{{ else }}
4543
{{ errorf "Unable to get remote resource: %s" $url }}
44+
{{ end }}
4645
{{ end }}
4746
`
4847

@@ -90,14 +89,15 @@ mediaTypes = ['text/plain']
9089
-- layouts/_default/single.html --
9190
{{ $url := printf "%s%s" "URL" .RelPermalink}}
9291
{{ $opts := dict }}
93-
{{ with resources.GetRemote $url $opts }}
92+
{{ with try (resources.GetRemote $url $opts) }}
9493
{{ with .Err }}
95-
{{ errorf "Got Err: %s. Data: %v" . .Data }}
96-
{{ else }}
94+
{{ errorf "Got Err: %s" . }}
95+
{{ with .Cause }}{{ errorf "Data: %s" .Data }}{{ end }}
96+
{{ else with .Value }}
9797
Content: {{ .Content }}
98+
{{ else }}
99+
{{ errorf "Unable to get remote resource: %s" $url }}
98100
{{ end }}
99-
{{ else }}
100-
{{ errorf "Unable to get remote resource: %s" $url }}
101101
{{ end }}
102102
`
103103

resources/transform.go

-4
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,6 @@ func (r *resourceAdapter) Content(ctx context.Context) (any, error) {
192192
return r.target.Content(ctx)
193193
}
194194

195-
func (r *resourceAdapter) Err() resource.ResourceError {
196-
return nil
197-
}
198-
199195
func (r *resourceAdapter) GetIdentity() identity.Identity {
200196
return identity.FirstIdentity(r.target)
201197
}

0 commit comments

Comments
 (0)