diff --git a/Makefile b/Makefile index f60e9e5a..e1884d96 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,10 @@ BINARY_NAME=song-stitch mod: go mod tidy go mod vendor + go mod verify go-update: - go get -u ./... + go list -mod=readonly -m -f '{{if not .Indirect}}{{if not .Main}}{{.Path}}{{end}}{{end}}' all | xargs go get -u $(MAKE) mod hadolint: diff --git a/go.mod b/go.mod index a8448e1d..ac68b46e 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( require ( github.com/andybalholm/cascadia v1.3.2 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/ggicci/owl v0.4.0 // indirect + github.com/ggicci/owl v0.6.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect @@ -27,9 +27,9 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/rs/xid v1.5.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/image v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/image v0.14.0 // indirect + golang.org/x/net v0.18.0 // indirect golang.org/x/sys v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index c297926a..de278739 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,8 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ggicci/httpin v0.14.2 h1:rGrG/OgXg3XZbRBBcqf8TSeu1nW9XX6L9F42XGhwgRQ= github.com/ggicci/httpin v0.14.2/go.mod h1:m/RhY5rRPkNQs4VMPK66LxBX4ZMPxPyXQvrnmBEo2Y8= -github.com/ggicci/owl v0.4.0 h1:1cwRlynLe6P5ylLyjNWtOP5qVO1bYUmziPYVbOphGHQ= -github.com/ggicci/owl v0.4.0/go.mod h1:TRPWshRwYej6uES//YW5aNgLB370URwyta1Ytfs7KXs= +github.com/ggicci/owl v0.6.0 h1:Z5+MBU4nrvFSV0PQGythmE/uiJntMkiCRgU5VRg5haE= +github.com/ggicci/owl v0.6.0/go.mod h1:TRPWshRwYej6uES//YW5aNgLB370URwyta1Ytfs7KXs= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -69,10 +69,10 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= -golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= +golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -82,8 +82,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/vendor/github.com/ggicci/owl/context.go b/vendor/github.com/ggicci/owl/context.go index 28dd1699..b67747ae 100644 --- a/vendor/github.com/ggicci/owl/context.go +++ b/vendor/github.com/ggicci/owl/context.go @@ -4,4 +4,6 @@ type contextKey int const ( ckNamespace contextKey = iota + ckResolveNestedDirectives + ckDirectiveRunOrder ) diff --git a/vendor/github.com/ggicci/owl/option.go b/vendor/github.com/ggicci/owl/option.go index 33855840..8df24751 100644 --- a/vendor/github.com/ggicci/owl/option.go +++ b/vendor/github.com/ggicci/owl/option.go @@ -2,22 +2,53 @@ package owl import "context" +// Option is an option for New. type Option interface { Apply(context.Context) context.Context } +// OptionFunc is a function that implements Option. type OptionFunc func(context.Context) context.Context func (f OptionFunc) Apply(ctx context.Context) context.Context { return f(ctx) } +// WithNamespace binds a namespace to the resolver. The namespace is used to +// lookup directive executors. There's a default namespace, which is used when +// the namespace is not specified. The namespace set in New will be overridden +// by the namespace set in Resolve or Scan. +func WithNamespace(ns *Namespace) Option { + return WithValue(ckNamespace, ns) +} + +// WithValue binds a value to the context. +// +// When used in New, the value is bound to Resolver.Context. +// +// When used in Resolve or Scan, the value is bound to DirectiveRuntime.Context. +// See DirectiveRuntime.Context for more details. func WithValue(key, value interface{}) Option { return OptionFunc(func(ctx context.Context) context.Context { return context.WithValue(ctx, key, value) }) } -func WithNamespace(ns *Namespace) Option { - return WithValue(ckNamespace, ns) +// WithNestedDirectivesEnabled controls whether to resolve nested directives. +// The default value is true. When set to false, the nested directives will not +// be executed. The value set in New will be overridden by the value set in +// Resolve or Scan. +func WithNestedDirectivesEnabled(resolve bool) Option { + return WithValue(ckResolveNestedDirectives, resolve) +} + +type DirectiveRunOrder func(*Directive, *Directive) bool + +// WithDirectiveRunOrder sets the order of execution for directives. +// +// When used in New, the directives will be sorted at the tree building stage. +// +// When Used in Resolve or Scan, a copy of the directives will be sorted and used. +func WithDirectiveRunOrder(runOrder DirectiveRunOrder) Option { + return WithValue(ckDirectiveRunOrder, runOrder) } diff --git a/vendor/github.com/ggicci/owl/resolver.go b/vendor/github.com/ggicci/owl/resolver.go index 3e0a2dac..171d7672 100644 --- a/vendor/github.com/ggicci/owl/resolver.go +++ b/vendor/github.com/ggicci/owl/resolver.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "reflect" + "sort" "strconv" "strings" "sync" @@ -55,12 +56,12 @@ func New(structValue interface{}, opts ...Option) (*Resolver, error) { // Apply the context to each resolver. tree.Iterate(func(r *Resolver) error { r.Context = ctx + r.Directives = getSortedDirectives(ctx, r.Directives) return nil }) - // Validate the tree. - if err := tree.validate(); err != nil { - return nil, err + if tree.Namespace() == nil { + return nil, errors.New("nil namespace") } return tree, nil @@ -80,14 +81,6 @@ func (r *Resolver) copy() *Resolver { return resolverCopy } -func (r *Resolver) validate() error { - if r.Namespace() == nil { - return errors.New("nil namespace") - } - - return nil -} - func (r *Resolver) IsRoot() bool { return r.Parent == nil } @@ -146,28 +139,49 @@ func findResolver(root *Resolver, path []string) *Resolver { return nil } +func shouldResolveNestedDirectives(r *Resolver, ctx context.Context) bool { + if r.IsRoot() { + return true // always resolve the root + } + if r.IsLeaf() { + return false // leaves have no children + } + if len(r.Directives) == 0 { + return true // go deeper if no directives on current field + } + if ctx != nil && ctx.Value(ckResolveNestedDirectives) != nil { + return ctx.Value(ckResolveNestedDirectives).(bool) + } + if r.Context.Value(ckResolveNestedDirectives) != nil { + return r.Context.Value(ckResolveNestedDirectives).(bool) + } + return true +} + func (r *Resolver) String() string { return fmt.Sprintf("%s (%v)", r.PathString(), r.Type) } -// Iterate visits the resolver tree by depth-first. The callback function -// will be called for each field resolver. If the callback returns an error, -// the iteration will be stopped. +// Iterate visits the resolver tree by depth-first. The callback function will +// be called on each field resolver. The iteration will stop if the callback +// returns an error. func (r *Resolver) Iterate(fn func(*Resolver) error) error { - return iterateResolverTree(r, fn) + ctx := WithValue(ckResolveNestedDirectives, true).Apply(context.Background()) + return r.iterate(ctx, fn) } -func iterateResolverTree(root *Resolver, fn func(*Resolver) error) error { +func (root *Resolver) iterate(ctx context.Context, fn func(*Resolver) error) error { if err := fn(root); err != nil { return err } - for _, field := range root.Children { - if err := iterateResolverTree(field, fn); err != nil { - return err + if shouldResolveNestedDirectives(root, ctx) { + for _, field := range root.Children { + if err := field.iterate(ctx, fn); err != nil { + return err + } } } - return nil } @@ -206,7 +220,7 @@ func (r *Resolver) Scan(value any, opts ...Option) error { } var errs []error - r.Iterate(func(r *Resolver) error { + r.iterate(ctx, func(r *Resolver) error { errs = append(errs, scan(r, ctx, rv)) return nil }) @@ -274,7 +288,7 @@ func (root *Resolver) resolve(ctx context.Context, rootValue reflect.Value) erro } // Resolve the children fields. - if len(root.Children) > 0 { + if shouldResolveNestedDirectives(root, ctx) { // If the root is a pointer, we need to allocate memory for it. // We only expect it's a one-level pointer, e.g. *User, not **User. underlyingValue := rootValue @@ -305,7 +319,7 @@ func (r *Resolver) runDirectives(ctx context.Context, rv reflect.Value) error { ns = nsOverriden.(*Namespace) } - for _, directive := range r.Directives { + for _, directive := range getSortedDirectives(ctx, r.Directives) { dirRuntime := &DirectiveRuntime{ Directive: directive, Resolver: r, @@ -333,6 +347,18 @@ func (r *Resolver) runDirectives(ctx context.Context, rv reflect.Value) error { return nil } +func getSortedDirectives(ctx context.Context, directives []*Directive) []*Directive { + if directiveRunOrder := ctx.Value(ckDirectiveRunOrder); directiveRunOrder != nil { + var directivesCopy []*Directive + directivesCopy = append(directivesCopy, directives...) + sort.SliceStable(directivesCopy, func(i, j int) bool { + return directiveRunOrder.(DirectiveRunOrder)(directivesCopy[i], directivesCopy[j]) + }) + return directivesCopy + } + return directives // the original one +} + func (r *Resolver) DebugLayoutText(depth int) string { var sb strings.Builder sb.WriteString(r.String()) diff --git a/vendor/golang.org/x/crypto/sha3/hashes_generic.go b/vendor/golang.org/x/crypto/sha3/hashes_generic.go index c74fc20f..fe8c8479 100644 --- a/vendor/golang.org/x/crypto/sha3/hashes_generic.go +++ b/vendor/golang.org/x/crypto/sha3/hashes_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !gc || purego || !s390x -// +build !gc purego !s390x package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/keccakf.go b/vendor/golang.org/x/crypto/sha3/keccakf.go index e5faa375..ce48b1dd 100644 --- a/vendor/golang.org/x/crypto/sha3/keccakf.go +++ b/vendor/golang.org/x/crypto/sha3/keccakf.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 || purego || !gc -// +build !amd64 purego !gc package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go index 248a3824..b908696b 100644 --- a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go +++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && !purego && gc -// +build amd64,!purego,gc package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s index 4cfa5438..8fb26aeb 100644 --- a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s +++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && !purego && gc -// +build amd64,!purego,gc // This code was translated into a form compatible with 6a from the public // domain sources at https://github.com/gvanas/KeccakCodePackage diff --git a/vendor/golang.org/x/crypto/sha3/register.go b/vendor/golang.org/x/crypto/sha3/register.go index 8b4453aa..addfd504 100644 --- a/vendor/golang.org/x/crypto/sha3/register.go +++ b/vendor/golang.org/x/crypto/sha3/register.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.4 -// +build go1.4 package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go index ec26f147..d861bca5 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc && !purego -// +build gc,!purego package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s index a0e051b0..826b862c 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc && !purego -// +build gc,!purego #include "textflag.h" diff --git a/vendor/golang.org/x/crypto/sha3/shake_generic.go b/vendor/golang.org/x/crypto/sha3/shake_generic.go index 5c0710ef..8d31cf5b 100644 --- a/vendor/golang.org/x/crypto/sha3/shake_generic.go +++ b/vendor/golang.org/x/crypto/sha3/shake_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !gc || purego || !s390x -// +build !gc purego !s390x package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/xor.go b/vendor/golang.org/x/crypto/sha3/xor.go index 59c8eb94..7337cca8 100644 --- a/vendor/golang.org/x/crypto/sha3/xor.go +++ b/vendor/golang.org/x/crypto/sha3/xor.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (!amd64 && !386 && !ppc64le) || purego -// +build !amd64,!386,!ppc64le purego package sha3 diff --git a/vendor/golang.org/x/crypto/sha3/xor_unaligned.go b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go index 1ce60624..870e2d16 100644 --- a/vendor/golang.org/x/crypto/sha3/xor_unaligned.go +++ b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (amd64 || 386 || ppc64le) && !purego -// +build amd64 386 ppc64le -// +build !purego package sha3 diff --git a/vendor/modules.txt b/vendor/modules.txt index 73dd9634..4308c039 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -22,7 +22,7 @@ github.com/gabriel-vasile/mimetype/internal/magic # github.com/ggicci/httpin v0.14.2 ## explicit; go 1.20 github.com/ggicci/httpin -# github.com/ggicci/owl v0.4.0 +# github.com/ggicci/owl v0.6.0 ## explicit; go 1.20 github.com/ggicci/owl # github.com/go-playground/locales v0.14.1 @@ -71,18 +71,18 @@ github.com/rs/zerolog/log # github.com/sethvargo/go-envconfig v0.9.0 ## explicit; go 1.17 github.com/sethvargo/go-envconfig -# golang.org/x/crypto v0.14.0 -## explicit; go 1.17 +# golang.org/x/crypto v0.15.0 +## explicit; go 1.18 golang.org/x/crypto/sha3 -# golang.org/x/image v0.13.0 +# golang.org/x/image v0.14.0 ## explicit; go 1.18 golang.org/x/image/draw golang.org/x/image/font golang.org/x/image/font/basicfont golang.org/x/image/math/f64 golang.org/x/image/math/fixed -# golang.org/x/net v0.17.0 -## explicit; go 1.17 +# golang.org/x/net v0.18.0 +## explicit; go 1.18 golang.org/x/net/html golang.org/x/net/html/atom # golang.org/x/sys v0.14.0