diff --git a/go.mod b/go.mod index db4a3a5fc..6c8e05033 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,15 @@ go 1.16 require ( github.com/Masterminds/sprig/v3 v3.2.2 + github.com/google/go-cmp v0.5.6 // indirect github.com/google/gofuzz v1.1.0 github.com/json-iterator/go v1.1.11 // indirect github.com/spf13/pflag v1.0.5 + golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b // indirect gomodules.xyz/semvers v0.0.0-20210317131320-984e32dd89ca k8s.io/api v0.21.1 k8s.io/apimachinery v0.21.1 - kmodules.xyz/client-go v0.0.0-20210921150324-f005c6dfcb32 + kmodules.xyz/client-go v0.0.0-20210928133955-8df5bb467db6 kmodules.xyz/schema-checker v0.1.2 sigs.k8s.io/yaml v1.2.0 ) @@ -126,3 +128,5 @@ replace kmodules.xyz/resource-metadata => kmodules.xyz/resource-metadata v0.5.0 replace sigs.k8s.io/application => github.com/kmodules/application v0.8.4-0.20210427030912-90eeee3bc4ad replace github.com/satori/go.uuid => github.com/gofrs/uuid v4.0.0+incompatible + +replace github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt v3.2.1+incompatible diff --git a/go.sum b/go.sum index 14bdf4dff..0fe9521ab 100644 --- a/go.sum +++ b/go.sum @@ -84,7 +84,6 @@ github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4a github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -143,6 +142,7 @@ github.com/gobuffalo/flect v0.2.2/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20j github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -162,8 +162,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= @@ -467,8 +468,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b h1:wSOdpTq0/eI46Ez/LkDwIsAKA71YP2SRKBODiRWM0as= +golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= @@ -515,6 +517,7 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -679,8 +682,8 @@ k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/kube-aggregator v0.21.1/go.mod h1:cAZ0n02IiSl57sQSHz4vvrz3upQRMbytOiZnpPJaQzQ= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -kmodules.xyz/client-go v0.0.0-20210921150324-f005c6dfcb32 h1:ZXVJStHHjppRoaUw5JQ5KzMjK+EiY1GkcPigPHfkvSg= -kmodules.xyz/client-go v0.0.0-20210921150324-f005c6dfcb32/go.mod h1:0gkPeALtYjB27OHt4rd6+ZmMgoVTHVLtEJQeU23/gtA= +kmodules.xyz/client-go v0.0.0-20210928133955-8df5bb467db6 h1:o+SymmN26C8bqh1nLTFjT0UdOtAYrTLbp6v49iRe5MY= +kmodules.xyz/client-go v0.0.0-20210928133955-8df5bb467db6/go.mod h1:0gkPeALtYjB27OHt4rd6+ZmMgoVTHVLtEJQeU23/gtA= kmodules.xyz/schema-checker v0.1.2 h1:HiG8pg/ROi+6D3HROUpHBCjEWF2aYXPxmycH/c5wAR4= kmodules.xyz/schema-checker v0.1.2/go.mod h1:JyT3tjizU/gQY9bK56xzAvkjJoAaUPRam7HELx4Nb/o= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/hack/fmt/main.go b/hack/fmt/main.go index 36cc98077..ee0e93be6 100644 --- a/hack/fmt/main.go +++ b/hack/fmt/main.go @@ -273,9 +273,9 @@ func main() { func ListResources(dir string) ([]*unstructured.Unstructured, error) { var resources []*unstructured.Unstructured - err := parser.ProcessDir(dir, func(obj *unstructured.Unstructured) error { - obj.SetNamespace("") - resources = append(resources, obj) + err := parser.ProcessPath(dir, func(ri parser.ResourceInfo) error { + ri.Object.SetNamespace("") + resources = append(resources, ri.Object) return nil }) if err != nil { diff --git a/vendor/github.com/google/go-cmp/cmp/path.go b/vendor/github.com/google/go-cmp/cmp/path.go index 3d45c1a47..f01eff318 100644 --- a/vendor/github.com/google/go-cmp/cmp/path.go +++ b/vendor/github.com/google/go-cmp/cmp/path.go @@ -315,7 +315,7 @@ func (tf Transform) Option() Option { return tf.trans } // pops the address from the stack. Thus, when traversing into a pointer from // reflect.Ptr, reflect.Slice element, or reflect.Map, we can detect cycles // by checking whether the pointer has already been visited. The cycle detection -// uses a seperate stack for the x and y values. +// uses a separate stack for the x and y values. // // If a cycle is detected we need to determine whether the two pointers // should be considered equal. The definition of equality chosen by Equal diff --git a/vendor/github.com/google/go-cmp/cmp/report_compare.go b/vendor/github.com/google/go-cmp/cmp/report_compare.go index a6c070cfc..104bb3053 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_compare.go +++ b/vendor/github.com/google/go-cmp/cmp/report_compare.go @@ -79,7 +79,7 @@ func (opts formatOptions) verbosity() uint { } } -const maxVerbosityPreset = 3 +const maxVerbosityPreset = 6 // verbosityPreset modifies the verbosity settings given an index // between 0 and maxVerbosityPreset, inclusive. @@ -100,7 +100,7 @@ func verbosityPreset(opts formatOptions, i int) formatOptions { func (opts formatOptions) FormatDiff(v *valueNode, ptrs *pointerReferences) (out textNode) { if opts.DiffMode == diffIdentical { opts = opts.WithVerbosity(1) - } else { + } else if opts.verbosity() < 3 { opts = opts.WithVerbosity(3) } diff --git a/vendor/github.com/google/go-cmp/cmp/report_slices.go b/vendor/github.com/google/go-cmp/cmp/report_slices.go index da04caf16..2ad3bc85b 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_slices.go +++ b/vendor/github.com/google/go-cmp/cmp/report_slices.go @@ -7,6 +7,7 @@ package cmp import ( "bytes" "fmt" + "math" "reflect" "strconv" "strings" @@ -26,8 +27,6 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool { return false // No differences detected case !v.ValueX.IsValid() || !v.ValueY.IsValid(): return false // Both values must be valid - case v.Type.Kind() == reflect.Slice && (v.ValueX.Len() == 0 || v.ValueY.Len() == 0): - return false // Both slice values have to be non-empty case v.NumIgnored > 0: return false // Some ignore option was used case v.NumTransformed > 0: @@ -45,7 +44,16 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool { return false } - switch t := v.Type; t.Kind() { + // Check whether this is an interface with the same concrete types. + t := v.Type + vx, vy := v.ValueX, v.ValueY + if t.Kind() == reflect.Interface && !vx.IsNil() && !vy.IsNil() && vx.Elem().Type() == vy.Elem().Type() { + vx, vy = vx.Elem(), vy.Elem() + t = vx.Type() + } + + // Check whether we provide specialized diffing for this type. + switch t.Kind() { case reflect.String: case reflect.Array, reflect.Slice: // Only slices of primitive types have specialized handling. @@ -57,6 +65,11 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool { return false } + // Both slice values have to be non-empty. + if t.Kind() == reflect.Slice && (vx.Len() == 0 || vy.Len() == 0) { + return false + } + // If a sufficient number of elements already differ, // use specialized formatting even if length requirement is not met. if v.NumDiff > v.NumSame { @@ -68,7 +81,7 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool { // Use specialized string diffing for longer slices or strings. const minLength = 64 - return v.ValueX.Len() >= minLength && v.ValueY.Len() >= minLength + return vx.Len() >= minLength && vy.Len() >= minLength } // FormatDiffSlice prints a diff for the slices (or strings) represented by v. @@ -77,17 +90,23 @@ func (opts formatOptions) CanFormatDiffSlice(v *valueNode) bool { func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { assert(opts.DiffMode == diffUnknown) t, vx, vy := v.Type, v.ValueX, v.ValueY + if t.Kind() == reflect.Interface { + vx, vy = vx.Elem(), vy.Elem() + t = vx.Type() + opts = opts.WithTypeMode(emitType) + } // Auto-detect the type of the data. - var isLinedText, isText, isBinary bool var sx, sy string + var ssx, ssy []string + var isString, isMostlyText, isPureLinedText, isBinary bool switch { case t.Kind() == reflect.String: sx, sy = vx.String(), vy.String() - isText = true // Initial estimate, verify later + isString = true case t.Kind() == reflect.Slice && t.Elem() == reflect.TypeOf(byte(0)): sx, sy = string(vx.Bytes()), string(vy.Bytes()) - isBinary = true // Initial estimate, verify later + isString = true case t.Kind() == reflect.Array: // Arrays need to be addressable for slice operations to work. vx2, vy2 := reflect.New(t).Elem(), reflect.New(t).Elem() @@ -95,13 +114,12 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { vy2.Set(vy) vx, vy = vx2, vy2 } - if isText || isBinary { - var numLines, lastLineIdx, maxLineLen int - isBinary = !utf8.ValidString(sx) || !utf8.ValidString(sy) + if isString { + var numTotalRunes, numValidRunes, numLines, lastLineIdx, maxLineLen int for i, r := range sx + sy { - if !(unicode.IsPrint(r) || unicode.IsSpace(r)) || r == utf8.RuneError { - isBinary = true - break + numTotalRunes++ + if (unicode.IsPrint(r) || unicode.IsSpace(r)) && r != utf8.RuneError { + numValidRunes++ } if r == '\n' { if maxLineLen < i-lastLineIdx { @@ -111,8 +129,26 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { numLines++ } } - isText = !isBinary - isLinedText = isText && numLines >= 4 && maxLineLen <= 1024 + isPureText := numValidRunes == numTotalRunes + isMostlyText = float64(numValidRunes) > math.Floor(0.90*float64(numTotalRunes)) + isPureLinedText = isPureText && numLines >= 4 && maxLineLen <= 1024 + isBinary = !isMostlyText + + // Avoid diffing by lines if it produces a significantly more complex + // edit script than diffing by bytes. + if isPureLinedText { + ssx = strings.Split(sx, "\n") + ssy = strings.Split(sy, "\n") + esLines := diff.Difference(len(ssx), len(ssy), func(ix, iy int) diff.Result { + return diff.BoolResult(ssx[ix] == ssy[iy]) + }) + esBytes := diff.Difference(len(sx), len(sy), func(ix, iy int) diff.Result { + return diff.BoolResult(sx[ix] == sy[iy]) + }) + efficiencyLines := float64(esLines.Dist()) / float64(len(esLines)) + efficiencyBytes := float64(esBytes.Dist()) / float64(len(esBytes)) + isPureLinedText = efficiencyLines < 4*efficiencyBytes + } } // Format the string into printable records. @@ -121,9 +157,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { switch { // If the text appears to be multi-lined text, // then perform differencing across individual lines. - case isLinedText: - ssx := strings.Split(sx, "\n") - ssy := strings.Split(sy, "\n") + case isPureLinedText: list = opts.formatDiffSlice( reflect.ValueOf(ssx), reflect.ValueOf(ssy), 1, "line", func(v reflect.Value, d diffMode) textRecord { @@ -212,7 +246,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { // If the text appears to be single-lined text, // then perform differencing in approximately fixed-sized chunks. // The output is printed as quoted strings. - case isText: + case isMostlyText: list = opts.formatDiffSlice( reflect.ValueOf(sx), reflect.ValueOf(sy), 64, "byte", func(v reflect.Value, d diffMode) textRecord { @@ -220,7 +254,6 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { return textRecord{Diff: d, Value: textLine(s)} }, ) - delim = "" // If the text appears to be binary data, // then perform differencing in approximately fixed-sized chunks. @@ -282,7 +315,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { // Wrap the output with appropriate type information. var out textNode = &textWrap{Prefix: "{", Value: list, Suffix: "}"} - if !isText { + if !isMostlyText { // The "{...}" byte-sequence literal is not valid Go syntax for strings. // Emit the type for extra clarity (e.g. "string{...}"). if t.Kind() == reflect.String { @@ -321,8 +354,11 @@ func (opts formatOptions) formatDiffSlice( vx, vy reflect.Value, chunkSize int, name string, makeRec func(reflect.Value, diffMode) textRecord, ) (list textList) { - es := diff.Difference(vx.Len(), vy.Len(), func(ix int, iy int) diff.Result { - return diff.BoolResult(vx.Index(ix).Interface() == vy.Index(iy).Interface()) + eq := func(ix, iy int) bool { + return vx.Index(ix).Interface() == vy.Index(iy).Interface() + } + es := diff.Difference(vx.Len(), vy.Len(), func(ix, iy int) diff.Result { + return diff.BoolResult(eq(ix, iy)) }) appendChunks := func(v reflect.Value, d diffMode) int { @@ -347,6 +383,7 @@ func (opts formatOptions) formatDiffSlice( groups := coalesceAdjacentEdits(name, es) groups = coalesceInterveningIdentical(groups, chunkSize/4) + groups = cleanupSurroundingIdentical(groups, eq) maxGroup := diffStats{Name: name} for i, ds := range groups { if maxLen >= 0 && numDiffs >= maxLen { @@ -399,25 +436,36 @@ func (opts formatOptions) formatDiffSlice( // coalesceAdjacentEdits coalesces the list of edits into groups of adjacent // equal or unequal counts. +// +// Example: +// +// Input: "..XXY...Y" +// Output: [ +// {NumIdentical: 2}, +// {NumRemoved: 2, NumInserted 1}, +// {NumIdentical: 3}, +// {NumInserted: 1}, +// ] +// func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) { - var prevCase int // Arbitrary index into which case last occurred - lastStats := func(i int) *diffStats { - if prevCase != i { + var prevMode byte + lastStats := func(mode byte) *diffStats { + if prevMode != mode { groups = append(groups, diffStats{Name: name}) - prevCase = i + prevMode = mode } return &groups[len(groups)-1] } for _, e := range es { switch e { case diff.Identity: - lastStats(1).NumIdentical++ + lastStats('=').NumIdentical++ case diff.UniqueX: - lastStats(2).NumRemoved++ + lastStats('!').NumRemoved++ case diff.UniqueY: - lastStats(2).NumInserted++ + lastStats('!').NumInserted++ case diff.Modified: - lastStats(2).NumModified++ + lastStats('!').NumModified++ } } return groups @@ -427,6 +475,35 @@ func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) // equal groups into adjacent unequal groups that currently result in a // dual inserted/removed printout. This acts as a high-pass filter to smooth // out high-frequency changes within the windowSize. +// +// Example: +// +// WindowSize: 16, +// Input: [ +// {NumIdentical: 61}, // group 0 +// {NumRemoved: 3, NumInserted: 1}, // group 1 +// {NumIdentical: 6}, // ├── coalesce +// {NumInserted: 2}, // ├── coalesce +// {NumIdentical: 1}, // ├── coalesce +// {NumRemoved: 9}, // └── coalesce +// {NumIdentical: 64}, // group 2 +// {NumRemoved: 3, NumInserted: 1}, // group 3 +// {NumIdentical: 6}, // ├── coalesce +// {NumInserted: 2}, // ├── coalesce +// {NumIdentical: 1}, // ├── coalesce +// {NumRemoved: 7}, // ├── coalesce +// {NumIdentical: 1}, // ├── coalesce +// {NumRemoved: 2}, // └── coalesce +// {NumIdentical: 63}, // group 4 +// ] +// Output: [ +// {NumIdentical: 61}, +// {NumIdentical: 7, NumRemoved: 12, NumInserted: 3}, +// {NumIdentical: 64}, +// {NumIdentical: 8, NumRemoved: 12, NumInserted: 3}, +// {NumIdentical: 63}, +// ] +// func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStats { groups, groupsOrig := groups[:0], groups for i, ds := range groupsOrig { @@ -446,3 +523,91 @@ func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStat } return groups } + +// cleanupSurroundingIdentical scans through all unequal groups, and +// moves any leading sequence of equal elements to the preceding equal group and +// moves and trailing sequence of equal elements to the succeeding equal group. +// +// This is necessary since coalesceInterveningIdentical may coalesce edit groups +// together such that leading/trailing spans of equal elements becomes possible. +// Note that this can occur even with an optimal diffing algorithm. +// +// Example: +// +// Input: [ +// {NumIdentical: 61}, +// {NumIdentical: 1 , NumRemoved: 11, NumInserted: 2}, // assume 3 leading identical elements +// {NumIdentical: 67}, +// {NumIdentical: 7, NumRemoved: 12, NumInserted: 3}, // assume 10 trailing identical elements +// {NumIdentical: 54}, +// ] +// Output: [ +// {NumIdentical: 64}, // incremented by 3 +// {NumRemoved: 9}, +// {NumIdentical: 67}, +// {NumRemoved: 9}, +// {NumIdentical: 64}, // incremented by 10 +// ] +// +func cleanupSurroundingIdentical(groups []diffStats, eq func(i, j int) bool) []diffStats { + var ix, iy int // indexes into sequence x and y + for i, ds := range groups { + // Handle equal group. + if ds.NumDiff() == 0 { + ix += ds.NumIdentical + iy += ds.NumIdentical + continue + } + + // Handle unequal group. + nx := ds.NumIdentical + ds.NumRemoved + ds.NumModified + ny := ds.NumIdentical + ds.NumInserted + ds.NumModified + var numLeadingIdentical, numTrailingIdentical int + for i := 0; i < nx && i < ny && eq(ix+i, iy+i); i++ { + numLeadingIdentical++ + } + for i := 0; i < nx && i < ny && eq(ix+nx-1-i, iy+ny-1-i); i++ { + numTrailingIdentical++ + } + if numIdentical := numLeadingIdentical + numTrailingIdentical; numIdentical > 0 { + if numLeadingIdentical > 0 { + // Remove leading identical span from this group and + // insert it into the preceding group. + if i-1 >= 0 { + groups[i-1].NumIdentical += numLeadingIdentical + } else { + // No preceding group exists, so prepend a new group, + // but do so after we finish iterating over all groups. + defer func() { + groups = append([]diffStats{{Name: groups[0].Name, NumIdentical: numLeadingIdentical}}, groups...) + }() + } + // Increment indexes since the preceding group would have handled this. + ix += numLeadingIdentical + iy += numLeadingIdentical + } + if numTrailingIdentical > 0 { + // Remove trailing identical span from this group and + // insert it into the succeeding group. + if i+1 < len(groups) { + groups[i+1].NumIdentical += numTrailingIdentical + } else { + // No succeeding group exists, so append a new group, + // but do so after we finish iterating over all groups. + defer func() { + groups = append(groups, diffStats{Name: groups[len(groups)-1].Name, NumIdentical: numTrailingIdentical}) + }() + } + // Do not increment indexes since the succeeding group will handle this. + } + + // Update this group since some identical elements were removed. + nx -= numIdentical + ny -= numIdentical + groups[i] = diffStats{Name: ds.Name, NumRemoved: nx, NumInserted: ny} + } + ix += nx + iy += ny + } + return groups +} diff --git a/vendor/kmodules.xyz/client-go/tools/parser/parser.go b/vendor/kmodules.xyz/client-go/tools/parser/parser.go index 8183d65b5..88932617e 100644 --- a/vendor/kmodules.xyz/client-go/tools/parser/parser.go +++ b/vendor/kmodules.xyz/client-go/tools/parser/parser.go @@ -33,9 +33,18 @@ import ( ylib "k8s.io/apimachinery/pkg/util/yaml" ) -type ResourceFn func(obj *unstructured.Unstructured) error +type ResourceInfo struct { + Filename string + Object *unstructured.Unstructured +} + +type ResourceFn func(ri ResourceInfo) error func ProcessResources(data []byte, fn ResourceFn) error { + return processResources("", data, fn) +} + +func processResources(filename string, data []byte, fn ResourceFn) error { reader := ylib.NewYAMLOrJSONDecoder(bytes.NewReader(data), 2048) for { var obj unstructured.Unstructured @@ -51,12 +60,18 @@ func ProcessResources(data []byte, fn ResourceFn) error { } if obj.IsList() { if err := obj.EachListItem(func(item runtime.Object) error { - return fn(item.(*unstructured.Unstructured)) + return fn(ResourceInfo{ + Filename: filename, + Object: item.(*unstructured.Unstructured), + }) }); err != nil { return err } } else { - if err := fn(&obj); err != nil { + if err := fn(ResourceInfo{ + Filename: filename, + Object: &obj, + }); err != nil { return err } } @@ -64,8 +79,8 @@ func ProcessResources(data []byte, fn ResourceFn) error { return nil } -func ProcessDir(dir string, fn ResourceFn) error { - return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { +func ProcessPath(root string, fn ResourceFn) error { + return filepath.WalkDir(root, func(path string, info os.DirEntry, err error) error { if err != nil { return err } @@ -82,7 +97,7 @@ func ProcessDir(dir string, fn ResourceFn) error { return err } - return ProcessResources(data, fn) + return processResources(path, data, fn) }) } @@ -104,18 +119,18 @@ func ProcessFS(fsys fs.FS, fn ResourceFn) error { return err } - return ProcessResources(data, fn) + return processResources(path, data, fn) }) } -func ListResources(data []byte) ([]*unstructured.Unstructured, error) { - var resources []*unstructured.Unstructured +func ListResources(data []byte) ([]ResourceInfo, error) { + var resources []ResourceInfo - err := ProcessResources(data, func(obj *unstructured.Unstructured) error { - if obj.GetNamespace() == "" { - obj.SetNamespace(core.NamespaceDefault) + err := processResources("", data, func(ri ResourceInfo) error { + if ri.Object.GetNamespace() == "" { + ri.Object.SetNamespace(core.NamespaceDefault) } - resources = append(resources, obj) + resources = append(resources, ri) return nil }) if err != nil { @@ -123,23 +138,23 @@ func ListResources(data []byte) ([]*unstructured.Unstructured, error) { } sort.Slice(resources, func(i, j int) bool { - if resources[i].GetAPIVersion() == resources[j].GetAPIVersion() { - return resources[i].GetKind() < resources[j].GetKind() + if resources[i].Object.GetAPIVersion() == resources[j].Object.GetAPIVersion() { + return resources[i].Object.GetKind() < resources[j].Object.GetKind() } - return resources[i].GetAPIVersion() < resources[j].GetAPIVersion() + return resources[i].Object.GetAPIVersion() < resources[j].Object.GetAPIVersion() }) return resources, nil } -func ListDirResources(dir string) ([]*unstructured.Unstructured, error) { - var resources []*unstructured.Unstructured +func ListPathResources(root string) ([]ResourceInfo, error) { + var resources []ResourceInfo - err := ProcessDir(dir, func(obj *unstructured.Unstructured) error { - if obj.GetNamespace() == "" { - obj.SetNamespace(core.NamespaceDefault) + err := ProcessPath(root, func(ri ResourceInfo) error { + if ri.Object.GetNamespace() == "" { + ri.Object.SetNamespace(core.NamespaceDefault) } - resources = append(resources, obj) + resources = append(resources, ri) return nil }) if err != nil { @@ -147,23 +162,23 @@ func ListDirResources(dir string) ([]*unstructured.Unstructured, error) { } sort.Slice(resources, func(i, j int) bool { - if resources[i].GetAPIVersion() == resources[j].GetAPIVersion() { - return resources[i].GetKind() < resources[j].GetKind() + if resources[i].Object.GetAPIVersion() == resources[j].Object.GetAPIVersion() { + return resources[i].Object.GetKind() < resources[j].Object.GetKind() } - return resources[i].GetAPIVersion() < resources[j].GetAPIVersion() + return resources[i].Object.GetAPIVersion() < resources[j].Object.GetAPIVersion() }) return resources, nil } -func ListFSResources(fsys fs.FS) ([]*unstructured.Unstructured, error) { - var resources []*unstructured.Unstructured +func ListFSResources(fsys fs.FS) ([]ResourceInfo, error) { + var resources []ResourceInfo - err := ProcessFS(fsys, func(obj *unstructured.Unstructured) error { - if obj.GetNamespace() == "" { - obj.SetNamespace(core.NamespaceDefault) + err := ProcessFS(fsys, func(ri ResourceInfo) error { + if ri.Object.GetNamespace() == "" { + ri.Object.SetNamespace(core.NamespaceDefault) } - resources = append(resources, obj) + resources = append(resources, ri) return nil }) if err != nil { @@ -171,10 +186,10 @@ func ListFSResources(fsys fs.FS) ([]*unstructured.Unstructured, error) { } sort.Slice(resources, func(i, j int) bool { - if resources[i].GetAPIVersion() == resources[j].GetAPIVersion() { - return resources[i].GetKind() < resources[j].GetKind() + if resources[i].Object.GetAPIVersion() == resources[j].Object.GetAPIVersion() { + return resources[i].Object.GetKind() < resources[j].Object.GetKind() } - return resources[i].GetAPIVersion() < resources[j].GetAPIVersion() + return resources[i].Object.GetAPIVersion() < resources[j].Object.GetAPIVersion() }) return resources, nil @@ -187,18 +202,18 @@ func ExtractComponents(data []byte) (map[metav1.GroupKind]struct{}, map[string]s commonLabels := map[string]string{} init := false - err := ProcessResources(data, func(obj *unstructured.Unstructured) error { - gv, err := schema.ParseGroupVersion(obj.GetAPIVersion()) + err := processResources("", data, func(ri ResourceInfo) error { + gv, err := schema.ParseGroupVersion(ri.Object.GetAPIVersion()) if err != nil { return err } - components[metav1.GroupKind{Group: gv.Group, Kind: obj.GetKind()}] = empty + components[metav1.GroupKind{Group: gv.Group, Kind: ri.Object.GetKind()}] = empty if !init { - commonLabels = obj.GetLabels() + commonLabels = ri.Object.GetLabels() init = true } else { - for k, v := range obj.GetLabels() { + for k, v := range ri.Object.GetLabels() { if existing, found := commonLabels[k]; found && existing != v { delete(commonLabels, k) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 757fa2e56..ff69ee5cc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -19,7 +19,8 @@ github.com/gogo/protobuf/sortkeys # github.com/golang/protobuf v1.5.2 => github.com/golang/protobuf v1.4.3 github.com/golang/protobuf/jsonpb github.com/golang/protobuf/proto -# github.com/google/go-cmp v0.5.4 +# github.com/google/go-cmp v0.5.6 +## explicit github.com/google/go-cmp/cmp github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags @@ -59,7 +60,8 @@ github.com/yudai/gojsondiff github.com/yudai/gojsondiff/formatter # github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 github.com/yudai/golcs -# golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 +# golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b +## explicit golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 @@ -154,7 +156,7 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/reflect # k8s.io/klog/v2 v2.8.0 k8s.io/klog/v2 -# kmodules.xyz/client-go v0.0.0-20210921150324-f005c6dfcb32 +# kmodules.xyz/client-go v0.0.0-20210928133955-8df5bb467db6 ## explicit kmodules.xyz/client-go/tools/parser # kmodules.xyz/schema-checker v0.1.2 @@ -221,3 +223,4 @@ sigs.k8s.io/yaml # kmodules.xyz/resource-metadata => kmodules.xyz/resource-metadata v0.5.0 # sigs.k8s.io/application => github.com/kmodules/application v0.8.4-0.20210427030912-90eeee3bc4ad # github.com/satori/go.uuid => github.com/gofrs/uuid v4.0.0+incompatible +# github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt v3.2.1+incompatible