Skip to content

Commit

Permalink
Fix union, complement, symdiff, and intersect for transient resources
Browse files Browse the repository at this point in the history
Fixes #13181
  • Loading branch information
bep committed Dec 22, 2024
1 parent 48a7aee commit 4a5e940
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 15 deletions.
32 changes: 21 additions & 11 deletions resources/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ var (
_ resource.Cloner = (*genericResource)(nil)
_ resource.ResourcesLanguageMerger = (*resource.Resources)(nil)
_ resource.Identifier = (*genericResource)(nil)
_ resource.TransientIdentifier = (*genericResource)(nil)
_ targetPathProvider = (*genericResource)(nil)
_ sourcePathProvider = (*genericResource)(nil)
_ identity.IdentityGroupProvider = (*genericResource)(nil)
Expand Down Expand Up @@ -359,6 +360,9 @@ func GetTestInfoForResource(r resource.Resource) GenericResourceTestInfo {
type genericResource struct {
publishInit *sync.Once

key string
keyInit *sync.Once

sd ResourceSourceDescriptor
paths internal.ResourcePaths

Expand Down Expand Up @@ -444,19 +448,24 @@ func (l *genericResource) Data() any {
}

func (l *genericResource) Key() string {
basePath := l.spec.Cfg.BaseURL().BasePathNoTrailingSlash
var key string
if basePath == "" {
key = l.RelPermalink()
} else {
key = strings.TrimPrefix(l.RelPermalink(), basePath)
}
l.keyInit.Do(func() {
basePath := l.spec.Cfg.BaseURL().BasePathNoTrailingSlash
if basePath == "" {
l.key = l.RelPermalink()
} else {
l.key = strings.TrimPrefix(l.RelPermalink(), basePath)
}

if l.spec.Cfg.IsMultihost() {
key = l.spec.Lang() + key
}
if l.spec.Cfg.IsMultihost() {
l.key = l.spec.Lang() + l.key
}
})

return l.key
}

return key
func (l *genericResource) TransientKey() string {
return l.Key()
}

func (l *genericResource) targetPath() string {
Expand Down Expand Up @@ -623,6 +632,7 @@ func (rc *genericResource) cloneWithUpdates(u *transformationUpdate) (baseResour

func (l genericResource) clone() *genericResource {
l.publishInit = &sync.Once{}
l.keyInit = &sync.Once{}
return &l
}

Expand Down
10 changes: 9 additions & 1 deletion resources/resource/resourcetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,19 @@ type ResourcesLanguageMerger interface {

// Identifier identifies a resource.
type Identifier interface {
// Key is is mostly for internal use and should be considered opaque.
// Key is mostly for internal use and should be considered opaque.
// This value may change between Hugo versions.
Key() string
}

// TransientIdentifier identifies a transient resource.
type TransientIdentifier interface {
// TransientKey is mostly for internal use and should be considered opaque.
// This value is implemented by transient resources where pointers may be short lived and
// not suitable for use as a map keys.
TransientKey() string
}

// WeightProvider provides a weight.
type WeightProvider interface {
Weight() int
Expand Down
1 change: 1 addition & 0 deletions resources/resource_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func (r *Spec) NewResource(rd ResourceSourceDescriptor) (resource.Resource, erro
Staler: &AtomicStaler{},
h: &resourceHash{},
publishInit: &sync.Once{},
keyInit: &sync.Once{},
paths: rp,
spec: r,
sd: rd,
Expand Down
6 changes: 6 additions & 0 deletions resources/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ var (
_ identity.IdentityGroupProvider = (*resourceAdapterInner)(nil)
_ resource.Source = (*resourceAdapter)(nil)
_ resource.Identifier = (*resourceAdapter)(nil)
_ resource.TransientIdentifier = (*resourceAdapter)(nil)
_ targetPathProvider = (*resourceAdapter)(nil)
_ sourcePathProvider = (*resourceAdapter)(nil)
_ resource.Identifier = (*resourceAdapter)(nil)
_ resource.ResourceNameTitleProvider = (*resourceAdapter)(nil)
_ resource.WithResourceMetaProvider = (*resourceAdapter)(nil)
_ identity.DependencyManagerProvider = (*resourceAdapter)(nil)
Expand Down Expand Up @@ -279,6 +281,10 @@ func (r *resourceAdapter) Key() string {
return r.target.(resource.Identifier).Key()
}

func (r *resourceAdapter) TransientKey() string {
return r.Key()
}

func (r *resourceAdapter) targetPath() string {
r.init(false, false)
return r.target.(targetPathProvider).targetPath()
Expand Down
29 changes: 29 additions & 0 deletions tpl/collections/collections_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,32 @@ tags: ['tag-b']
"2: Intersect: 1|\n2: Union: 3|\n2: SymDiff: 2|\n2: Uniq: 3|",
)
}

// Issue #13181
func TestUnionResourcesMatch(t *testing.T) {
t.Parallel()

files := `
-- config.toml --
disableKinds = ['rss','sitemap', 'taxonomy', 'term', 'page']
-- layouts/index.html --
{{ $a := resources.Match "*a*" }}
{{ $b := resources.Match "*b*" }}
{{ $union := $a | union $b }}
{{ range $i, $e := $union }}
{{ $i }}: {{ .Name }}
{{ end }}$
-- assets/a1.html --
<div>file1</div>
-- assets/a2.html --
<div>file2</div>
-- assets/a3_b1.html --
<div>file3</div>
-- assets/b2.html --
<div>file4</div>
`

b := hugolib.Test(t, files)

b.AssertFileContentExact("public/index.html", "0: /a3_b1.html\n\n1: /b2.html\n\n2: /a1.html\n\n3: /a2.html\n$")
}
12 changes: 9 additions & 3 deletions tpl/collections/reflect_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import (

"github.com/gohugoio/hugo/common/hashing"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/resources/resource"
)

var (
zero reflect.Value
errorType = reflect.TypeOf((*error)(nil)).Elem()
errorType = reflect.TypeFor[error]()
)

func numberToFloat(v reflect.Value) (float64, error) {
Expand Down Expand Up @@ -56,7 +57,13 @@ func normalize(v reflect.Value) any {
return f
}
}
return types.Unwrapv(v.Interface())

vv := types.Unwrapv(v.Interface())
if ip, ok := vv.(resource.TransientIdentifier); ok {
return ip.TransientKey()
}

return vv
}

// collects identities from the slices in seqs into a set. Numeric values are normalized,
Expand Down Expand Up @@ -151,7 +158,6 @@ func convertNumber(v reflect.Value, to reflect.Kind) (reflect.Value, error) {
case reflect.Uint64:
n = reflect.ValueOf(uint64(i))
}

}

if !n.IsValid() {
Expand Down

0 comments on commit 4a5e940

Please sign in to comment.