diff --git a/go.mod b/go.mod index 2ed8005ab073..b5a273489ab9 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,6 @@ require ( github.com/hashicorp/go-cty-funcs v0.0.0-20250818135842-6aab67130928 github.com/hashicorp/hcl/v2 v2.24.0 github.com/in-toto/in-toto-golang v0.11.0 - github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/moby/buildkit v0.33.0 github.com/moby/moby/api v1.55.0 github.com/moby/moby/client v0.5.0 diff --git a/go.sum b/go.sum index e4b03368b3c0..655d9329b8eb 100644 --- a/go.sum +++ b/go.sum @@ -389,8 +389,6 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/buildkit v0.33.0 h1:zBbt1FiMcTB/oFg1iCNcKa83k5Rn8MGcVjXFIcfYhuQ= diff --git a/util/progress/printer.go b/util/progress/printer.go index dcc2294569c1..eec6020e3024 100644 --- a/util/progress/printer.go +++ b/util/progress/printer.go @@ -1,19 +1,22 @@ package progress import ( + "bytes" "context" "io" "os" + "slices" "sync" "github.com/docker/buildx/util/logutil" - "github.com/mitchellh/hashstructure/v2" "github.com/moby/buildkit/client" + "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/progress/progressui" "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" + "google.golang.org/protobuf/proto" ) type printerState int @@ -295,28 +298,36 @@ func WithOnClose(onclose func()) PrinterOpt { } func dedupWarnings(inp []client.VertexWarning) []client.VertexWarning { - m := make(map[uint64]client.VertexWarning) + res := make([]client.VertexWarning, 0, len(inp)) for _, w := range inp { - wcp := w - wcp.Vertex = "" - if wcp.SourceInfo != nil { - wcp.SourceInfo.Definition = nil + if !slices.ContainsFunc(res, func(prev client.VertexWarning) bool { + return equalWarnings(prev, w) + }) { + res = append(res, w) } - h, err := hashstructure.Hash(wcp, hashstructure.FormatV2, nil) - if err != nil { - continue - } - if _, ok := m[h]; !ok { - m[h] = w - } - } - res := make([]client.VertexWarning, 0, len(m)) - for _, w := range m { - res = append(res, w) } return res } +// equalWarnings ignores the vertex and source definition, which can differ +// between otherwise identical warnings from separate builds. +func equalWarnings(a, b client.VertexWarning) bool { + if a.Level != b.Level || a.URL != b.URL || !bytes.Equal(a.Short, b.Short) || + !slices.EqualFunc(a.Detail, b.Detail, bytes.Equal) { + return false + } + if (a.SourceInfo == nil) != (b.SourceInfo == nil) { + return false + } + if a.SourceInfo != nil && (a.SourceInfo.Filename != b.SourceInfo.Filename || + a.SourceInfo.Language != b.SourceInfo.Language || !bytes.Equal(a.SourceInfo.Data, b.SourceInfo.Data)) { + return false + } + return slices.EqualFunc(a.Range, b.Range, func(a, b *pb.Range) bool { + return proto.Equal(a, b) + }) +} + type interruptRequest struct { desiredState printerState done chan<- struct{} diff --git a/util/progress/printer_test.go b/util/progress/printer_test.go new file mode 100644 index 000000000000..99d5b8f23851 --- /dev/null +++ b/util/progress/printer_test.go @@ -0,0 +1,69 @@ +package progress + +import ( + "testing" + + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/solver/pb" + "github.com/stretchr/testify/require" +) + +func TestDedupWarnings(t *testing.T) { + newWarning := func() client.VertexWarning { + return client.VertexWarning{ + Vertex: "first", + Level: 1, + Short: []byte("warning"), + Detail: [][]byte{[]byte("detail"), []byte("more detail")}, + URL: "https://example.com", + SourceInfo: &pb.SourceInfo{ + Filename: "Dockerfile", + Language: "dockerfile", + Data: []byte("FROM scratch"), + Definition: &pb.Definition{Def: [][]byte{[]byte("definition")}}, + }, + Range: []*pb.Range{{Start: &pb.Position{Line: 1}, End: &pb.Position{Line: 2}}}, + } + } + + t.Run("duplicates preserve first warning and inputs", func(t *testing.T) { + first, second := newWarning(), newWarning() + second.Vertex = "second" + second.SourceInfo.Definition = &pb.Definition{Def: [][]byte{[]byte("other definition")}} + got := dedupWarnings([]client.VertexWarning{first, second, first}) + require.Len(t, got, 1) + require.Equal(t, first, got[0]) + require.Equal(t, [][]byte{[]byte("definition")}, first.SourceInfo.Definition.Def) + require.Equal(t, [][]byte{[]byte("other definition")}, second.SourceInfo.Definition.Def) + }) + + for _, tc := range []struct { + name string + change func(*client.VertexWarning) + }{ + {"level", func(w *client.VertexWarning) { w.Level++ }}, + {"short", func(w *client.VertexWarning) { w.Short[0]++ }}, + {"detail", func(w *client.VertexWarning) { w.Detail[0][0]++ }}, + {"detail order", func(w *client.VertexWarning) { w.Detail[0], w.Detail[1] = w.Detail[1], w.Detail[0] }}, + {"url", func(w *client.VertexWarning) { w.URL += "/other" }}, + {"filename", func(w *client.VertexWarning) { w.SourceInfo.Filename += ".other" }}, + {"language", func(w *client.VertexWarning) { w.SourceInfo.Language = "other" }}, + {"source data", func(w *client.VertexWarning) { w.SourceInfo.Data[0]++ }}, + {"missing source", func(w *client.VertexWarning) { w.SourceInfo = nil }}, + {"range start", func(w *client.VertexWarning) { w.Range[0].Start.Line++ }}, + {"range end", func(w *client.VertexWarning) { w.Range[0].End.Character++ }}, + {"missing range", func(w *client.VertexWarning) { w.Range = nil }}, + } { + t.Run(tc.name, func(t *testing.T) { + first, second := newWarning(), newWarning() + tc.change(&second) + require.Equal(t, []client.VertexWarning{first, second}, dedupWarnings([]client.VertexWarning{first, second, first})) + }) + } + + t.Run("empty values", func(t *testing.T) { + require.Empty(t, dedupWarnings(nil)) + require.Len(t, dedupWarnings([]client.VertexWarning{{}, {Short: []byte{}, Detail: [][]byte{}, Range: []*pb.Range{}}}), 1) + require.Len(t, dedupWarnings([]client.VertexWarning{{}, {SourceInfo: &pb.SourceInfo{}}}), 2) + }) +} diff --git a/vendor/github.com/mitchellh/hashstructure/v2/LICENSE b/vendor/github.com/mitchellh/hashstructure/v2/LICENSE deleted file mode 100644 index a3866a291fd1..000000000000 --- a/vendor/github.com/mitchellh/hashstructure/v2/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Mitchell Hashimoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/hashstructure/v2/README.md b/vendor/github.com/mitchellh/hashstructure/v2/README.md deleted file mode 100644 index 21f36be193e1..000000000000 --- a/vendor/github.com/mitchellh/hashstructure/v2/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# hashstructure [![GoDoc](https://godoc.org/github.com/mitchellh/hashstructure?status.svg)](https://godoc.org/github.com/mitchellh/hashstructure) - -hashstructure is a Go library for creating a unique hash value -for arbitrary values in Go. - -This can be used to key values in a hash (for use in a map, set, etc.) -that are complex. The most common use case is comparing two values without -sending data across the network, caching values locally (de-dup), and so on. - -## Features - - * Hash any arbitrary Go value, including complex types. - - * Tag a struct field to ignore it and not affect the hash value. - - * Tag a slice type struct field to treat it as a set where ordering - doesn't affect the hash code but the field itself is still taken into - account to create the hash value. - - * Optionally, specify a custom hash function to optimize for speed, collision - avoidance for your data set, etc. - - * Optionally, hash the output of `.String()` on structs that implement fmt.Stringer, - allowing effective hashing of time.Time - - * Optionally, override the hashing process by implementing `Hashable`. - -## Installation - -Standard `go get`: - -``` -$ go get github.com/mitchellh/hashstructure/v2 -``` - -**Note on v2:** It is highly recommended you use the "v2" release since this -fixes some significant hash collisions issues from v1. In practice, we used -v1 for many years in real projects at HashiCorp and never had issues, but it -is highly dependent on the shape of the data you're hashing and how you use -those hashes. - -When using v2+, you can still generate weaker v1 hashes by using the -`FormatV1` format when calling `Hash`. - -## Usage & Example - -For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/hashstructure). - -A quick code example is shown below: - -```go -type ComplexStruct struct { - Name string - Age uint - Metadata map[string]interface{} -} - -v := ComplexStruct{ - Name: "mitchellh", - Age: 64, - Metadata: map[string]interface{}{ - "car": true, - "location": "California", - "siblings": []string{"Bob", "John"}, - }, -} - -hash, err := hashstructure.Hash(v, hashstructure.FormatV2, nil) -if err != nil { - panic(err) -} - -fmt.Printf("%d", hash) -// Output: -// 2307517237273902113 -``` diff --git a/vendor/github.com/mitchellh/hashstructure/v2/errors.go b/vendor/github.com/mitchellh/hashstructure/v2/errors.go deleted file mode 100644 index 44b8951478ec..000000000000 --- a/vendor/github.com/mitchellh/hashstructure/v2/errors.go +++ /dev/null @@ -1,22 +0,0 @@ -package hashstructure - -import ( - "fmt" -) - -// ErrNotStringer is returned when there's an error with hash:"string" -type ErrNotStringer struct { - Field string -} - -// Error implements error for ErrNotStringer -func (ens *ErrNotStringer) Error() string { - return fmt.Sprintf("hashstructure: %s has hash:\"string\" set, but does not implement fmt.Stringer", ens.Field) -} - -// ErrFormat is returned when an invalid format is given to the Hash function. -type ErrFormat struct{} - -func (*ErrFormat) Error() string { - return "format must be one of the defined Format values in the hashstructure library" -} diff --git a/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go b/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go deleted file mode 100644 index 3dc0eb74e07f..000000000000 --- a/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go +++ /dev/null @@ -1,482 +0,0 @@ -package hashstructure - -import ( - "encoding/binary" - "fmt" - "hash" - "hash/fnv" - "reflect" - "time" -) - -// HashOptions are options that are available for hashing. -type HashOptions struct { - // Hasher is the hash function to use. If this isn't set, it will - // default to FNV. - Hasher hash.Hash64 - - // TagName is the struct tag to look at when hashing the structure. - // By default this is "hash". - TagName string - - // ZeroNil is flag determining if nil pointer should be treated equal - // to a zero value of pointed type. By default this is false. - ZeroNil bool - - // IgnoreZeroValue is determining if zero value fields should be - // ignored for hash calculation. - IgnoreZeroValue bool - - // SlicesAsSets assumes that a `set` tag is always present for slices. - // Default is false (in which case the tag is used instead) - SlicesAsSets bool - - // UseStringer will attempt to use fmt.Stringer always. If the struct - // doesn't implement fmt.Stringer, it'll fall back to trying usual tricks. - // If this is true, and the "string" tag is also set, the tag takes - // precedence (meaning that if the type doesn't implement fmt.Stringer, we - // panic) - UseStringer bool -} - -// Format specifies the hashing process used. Different formats typically -// generate different hashes for the same value and have different properties. -type Format uint - -const ( - // To disallow the zero value - formatInvalid Format = iota - - // FormatV1 is the format used in v1.x of this library. This has the - // downsides noted in issue #18 but allows simultaneous v1/v2 usage. - FormatV1 - - // FormatV2 is the current recommended format and fixes the issues - // noted in FormatV1. - FormatV2 - - formatMax // so we can easily find the end -) - -// Hash returns the hash value of an arbitrary value. -// -// If opts is nil, then default options will be used. See HashOptions -// for the default values. The same *HashOptions value cannot be used -// concurrently. None of the values within a *HashOptions struct are -// safe to read/write while hashing is being done. -// -// The "format" is required and must be one of the format values defined -// by this library. You should probably just use "FormatV2". This allows -// generated hashes uses alternate logic to maintain compatibility with -// older versions. -// -// Notes on the value: -// -// * Unexported fields on structs are ignored and do not affect the -// hash value. -// -// * Adding an exported field to a struct with the zero value will change -// the hash value. -// -// For structs, the hashing can be controlled using tags. For example: -// -// struct { -// Name string -// UUID string `hash:"ignore"` -// } -// -// The available tag values are: -// -// * "ignore" or "-" - The field will be ignored and not affect the hash code. -// -// * "set" - The field will be treated as a set, where ordering doesn't -// affect the hash code. This only works for slices. -// -// * "string" - The field will be hashed as a string, only works when the -// field implements fmt.Stringer -// -func Hash(v interface{}, format Format, opts *HashOptions) (uint64, error) { - // Validate our format - if format <= formatInvalid || format >= formatMax { - return 0, &ErrFormat{} - } - - // Create default options - if opts == nil { - opts = &HashOptions{} - } - if opts.Hasher == nil { - opts.Hasher = fnv.New64() - } - if opts.TagName == "" { - opts.TagName = "hash" - } - - // Reset the hash - opts.Hasher.Reset() - - // Create our walker and walk the structure - w := &walker{ - format: format, - h: opts.Hasher, - tag: opts.TagName, - zeronil: opts.ZeroNil, - ignorezerovalue: opts.IgnoreZeroValue, - sets: opts.SlicesAsSets, - stringer: opts.UseStringer, - } - return w.visit(reflect.ValueOf(v), nil) -} - -type walker struct { - format Format - h hash.Hash64 - tag string - zeronil bool - ignorezerovalue bool - sets bool - stringer bool -} - -type visitOpts struct { - // Flags are a bitmask of flags to affect behavior of this visit - Flags visitFlag - - // Information about the struct containing this field - Struct interface{} - StructField string -} - -var timeType = reflect.TypeOf(time.Time{}) - -func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { - t := reflect.TypeOf(0) - - // Loop since these can be wrapped in multiple layers of pointers - // and interfaces. - for { - // If we have an interface, dereference it. We have to do this up - // here because it might be a nil in there and the check below must - // catch that. - if v.Kind() == reflect.Interface { - v = v.Elem() - continue - } - - if v.Kind() == reflect.Ptr { - if w.zeronil { - t = v.Type().Elem() - } - v = reflect.Indirect(v) - continue - } - - break - } - - // If it is nil, treat it like a zero. - if !v.IsValid() { - v = reflect.Zero(t) - } - - // Binary writing can use raw ints, we have to convert to - // a sized-int, we'll choose the largest... - switch v.Kind() { - case reflect.Int: - v = reflect.ValueOf(int64(v.Int())) - case reflect.Uint: - v = reflect.ValueOf(uint64(v.Uint())) - case reflect.Bool: - var tmp int8 - if v.Bool() { - tmp = 1 - } - v = reflect.ValueOf(tmp) - } - - k := v.Kind() - - // We can shortcut numeric values by directly binary writing them - if k >= reflect.Int && k <= reflect.Complex64 { - // A direct hash calculation - w.h.Reset() - err := binary.Write(w.h, binary.LittleEndian, v.Interface()) - return w.h.Sum64(), err - } - - switch v.Type() { - case timeType: - w.h.Reset() - b, err := v.Interface().(time.Time).MarshalBinary() - if err != nil { - return 0, err - } - - err = binary.Write(w.h, binary.LittleEndian, b) - return w.h.Sum64(), err - } - - switch k { - case reflect.Array: - var h uint64 - l := v.Len() - for i := 0; i < l; i++ { - current, err := w.visit(v.Index(i), nil) - if err != nil { - return 0, err - } - - h = hashUpdateOrdered(w.h, h, current) - } - - return h, nil - - case reflect.Map: - var includeMap IncludableMap - if opts != nil && opts.Struct != nil { - if v, ok := opts.Struct.(IncludableMap); ok { - includeMap = v - } - } - - // Build the hash for the map. We do this by XOR-ing all the key - // and value hashes. This makes it deterministic despite ordering. - var h uint64 - for _, k := range v.MapKeys() { - v := v.MapIndex(k) - if includeMap != nil { - incl, err := includeMap.HashIncludeMap( - opts.StructField, k.Interface(), v.Interface()) - if err != nil { - return 0, err - } - if !incl { - continue - } - } - - kh, err := w.visit(k, nil) - if err != nil { - return 0, err - } - vh, err := w.visit(v, nil) - if err != nil { - return 0, err - } - - fieldHash := hashUpdateOrdered(w.h, kh, vh) - h = hashUpdateUnordered(h, fieldHash) - } - - if w.format != FormatV1 { - // Important: read the docs for hashFinishUnordered - h = hashFinishUnordered(w.h, h) - } - - return h, nil - - case reflect.Struct: - parent := v.Interface() - var include Includable - if impl, ok := parent.(Includable); ok { - include = impl - } - - if impl, ok := parent.(Hashable); ok { - return impl.Hash() - } - - // If we can address this value, check if the pointer value - // implements our interfaces and use that if so. - if v.CanAddr() { - vptr := v.Addr() - parentptr := vptr.Interface() - if impl, ok := parentptr.(Includable); ok { - include = impl - } - - if impl, ok := parentptr.(Hashable); ok { - return impl.Hash() - } - } - - t := v.Type() - h, err := w.visit(reflect.ValueOf(t.Name()), nil) - if err != nil { - return 0, err - } - - l := v.NumField() - for i := 0; i < l; i++ { - if innerV := v.Field(i); v.CanSet() || t.Field(i).Name != "_" { - var f visitFlag - fieldType := t.Field(i) - if fieldType.PkgPath != "" { - // Unexported - continue - } - - tag := fieldType.Tag.Get(w.tag) - if tag == "ignore" || tag == "-" { - // Ignore this field - continue - } - - if w.ignorezerovalue { - if innerV.IsZero() { - continue - } - } - - // if string is set, use the string value - if tag == "string" || w.stringer { - if impl, ok := innerV.Interface().(fmt.Stringer); ok { - innerV = reflect.ValueOf(impl.String()) - } else if tag == "string" { - // We only show this error if the tag explicitly - // requests a stringer. - return 0, &ErrNotStringer{ - Field: v.Type().Field(i).Name, - } - } - } - - // Check if we implement includable and check it - if include != nil { - incl, err := include.HashInclude(fieldType.Name, innerV) - if err != nil { - return 0, err - } - if !incl { - continue - } - } - - switch tag { - case "set": - f |= visitFlagSet - } - - kh, err := w.visit(reflect.ValueOf(fieldType.Name), nil) - if err != nil { - return 0, err - } - - vh, err := w.visit(innerV, &visitOpts{ - Flags: f, - Struct: parent, - StructField: fieldType.Name, - }) - if err != nil { - return 0, err - } - - fieldHash := hashUpdateOrdered(w.h, kh, vh) - h = hashUpdateUnordered(h, fieldHash) - } - - if w.format != FormatV1 { - // Important: read the docs for hashFinishUnordered - h = hashFinishUnordered(w.h, h) - } - } - - return h, nil - - case reflect.Slice: - // We have two behaviors here. If it isn't a set, then we just - // visit all the elements. If it is a set, then we do a deterministic - // hash code. - var h uint64 - var set bool - if opts != nil { - set = (opts.Flags & visitFlagSet) != 0 - } - l := v.Len() - for i := 0; i < l; i++ { - current, err := w.visit(v.Index(i), nil) - if err != nil { - return 0, err - } - - if set || w.sets { - h = hashUpdateUnordered(h, current) - } else { - h = hashUpdateOrdered(w.h, h, current) - } - } - - if set && w.format != FormatV1 { - // Important: read the docs for hashFinishUnordered - h = hashFinishUnordered(w.h, h) - } - - return h, nil - - case reflect.String: - // Directly hash - w.h.Reset() - _, err := w.h.Write([]byte(v.String())) - return w.h.Sum64(), err - - default: - return 0, fmt.Errorf("unknown kind to hash: %s", k) - } - -} - -func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 { - // For ordered updates, use a real hash function - h.Reset() - - // We just panic if the binary writes fail because we are writing - // an int64 which should never be fail-able. - e1 := binary.Write(h, binary.LittleEndian, a) - e2 := binary.Write(h, binary.LittleEndian, b) - if e1 != nil { - panic(e1) - } - if e2 != nil { - panic(e2) - } - - return h.Sum64() -} - -func hashUpdateUnordered(a, b uint64) uint64 { - return a ^ b -} - -// After mixing a group of unique hashes with hashUpdateUnordered, it's always -// necessary to call hashFinishUnordered. Why? Because hashUpdateUnordered -// is a simple XOR, and calling hashUpdateUnordered on hashes produced by -// hashUpdateUnordered can effectively cancel out a previous change to the hash -// result if the same hash value appears later on. For example, consider: -// -// hashUpdateUnordered(hashUpdateUnordered("A", "B"), hashUpdateUnordered("A", "C")) = -// H("A") ^ H("B")) ^ (H("A") ^ H("C")) = -// (H("A") ^ H("A")) ^ (H("B") ^ H(C)) = -// H(B) ^ H(C) = -// hashUpdateUnordered(hashUpdateUnordered("Z", "B"), hashUpdateUnordered("Z", "C")) -// -// hashFinishUnordered "hardens" the result, so that encountering partially -// overlapping input data later on in a different context won't cancel out. -func hashFinishUnordered(h hash.Hash64, a uint64) uint64 { - h.Reset() - - // We just panic if the writes fail - e1 := binary.Write(h, binary.LittleEndian, a) - if e1 != nil { - panic(e1) - } - - return h.Sum64() -} - -// visitFlag is used as a bitmask for affecting visit behavior -type visitFlag uint - -const ( - visitFlagInvalid visitFlag = iota - visitFlagSet = iota << 1 -) diff --git a/vendor/github.com/mitchellh/hashstructure/v2/include.go b/vendor/github.com/mitchellh/hashstructure/v2/include.go deleted file mode 100644 index 702d35415d4a..000000000000 --- a/vendor/github.com/mitchellh/hashstructure/v2/include.go +++ /dev/null @@ -1,22 +0,0 @@ -package hashstructure - -// Includable is an interface that can optionally be implemented by -// a struct. It will be called for each field in the struct to check whether -// it should be included in the hash. -type Includable interface { - HashInclude(field string, v interface{}) (bool, error) -} - -// IncludableMap is an interface that can optionally be implemented by -// a struct. It will be called when a map-type field is found to ask the -// struct if the map item should be included in the hash. -type IncludableMap interface { - HashIncludeMap(field string, k, v interface{}) (bool, error) -} - -// Hashable is an interface that can optionally be implemented by a struct -// to override the hash value. This value will override the hash value for -// the entire struct. Entries in the struct will not be hashed. -type Hashable interface { - Hash() (uint64, error) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 3de18c8a4aaa..1b473f434421 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -641,9 +641,6 @@ github.com/mattn/go-shellwords # github.com/mitchellh/go-wordwrap v1.0.1 ## explicit; go 1.14 github.com/mitchellh/go-wordwrap -# github.com/mitchellh/hashstructure/v2 v2.0.2 -## explicit; go 1.14 -github.com/mitchellh/hashstructure/v2 # github.com/moby/buildkit v0.33.0 ## explicit; go 1.26.3 github.com/moby/buildkit/api/services/control