mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 00:47:48 +08:00

Update the buildflags cty code to handle unknown values. When hcl decodes a value with an invalid variable name, it appends a diagnostic for the error and then returns an unknown value so it can continue processing the file and finding more errors. The iteration code has now been changed to use a rangefunc from go 1.23 and it skips empty or unknown values. Empty values are valid when they are skipped and unknown values will have a diagnostic for itself. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
74 lines
1.6 KiB
Go
74 lines
1.6 KiB
Go
package buildflags
|
|
|
|
import (
|
|
"iter"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/gocty"
|
|
)
|
|
|
|
type comparable[E any] interface {
|
|
Equal(other E) bool
|
|
}
|
|
|
|
func removeDupes[E comparable[E]](s []E) []E {
|
|
// Move backwards through the slice.
|
|
// For each element, any elements after the current element are unique.
|
|
// If we find our current element conflicts with an existing element,
|
|
// then we swap the offender with the end of the slice and chop it off.
|
|
|
|
// Start at the second to last element.
|
|
// The last element is always unique.
|
|
for i := len(s) - 2; i >= 0; i-- {
|
|
elem := s[i]
|
|
// Check for duplicates after our current element.
|
|
for j := i + 1; j < len(s); j++ {
|
|
if elem.Equal(s[j]) {
|
|
// Found a duplicate, exchange the
|
|
// duplicate with the last element.
|
|
s[j], s[len(s)-1] = s[len(s)-1], s[j]
|
|
s = s[:len(s)-1]
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return s
|
|
}
|
|
|
|
func getAndDelete(m map[string]cty.Value, attr string, gv interface{}) error {
|
|
if v, ok := m[attr]; ok && v.IsKnown() {
|
|
delete(m, attr)
|
|
return gocty.FromCtyValue(v, gv)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func asMap(m map[string]cty.Value) map[string]string {
|
|
out := make(map[string]string, len(m))
|
|
for k, v := range m {
|
|
if v.IsKnown() {
|
|
out[k] = v.AsString()
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func isEmptyOrUnknown(v cty.Value) bool {
|
|
return !v.IsKnown() || (v.Type() == cty.String && v.AsString() == "")
|
|
}
|
|
|
|
func eachElement(in cty.Value) iter.Seq[cty.Value] {
|
|
return func(yield func(v cty.Value) bool) {
|
|
for elem := in.ElementIterator(); elem.Next(); {
|
|
_, value := elem.Element()
|
|
if isEmptyOrUnknown(value) {
|
|
continue
|
|
}
|
|
|
|
if !yield(value) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|