├── .github ├── dependabot.yml └── workflows │ ├── go.yml │ └── release.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yml ├── LICENSE ├── Makefile ├── README.md ├── cmd └── yaml-diff │ └── main.go ├── example ├── a.yaml └── b.yaml ├── go.mod ├── go.sum ├── tools ├── go.mod ├── go.sum └── tools.go └── yamldiff ├── diff.go ├── diff_test.go ├── printer.go ├── printer_test.go ├── yaml.go └── yaml_test.go /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gomod" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | on: 3 | push: 4 | pull_request: 5 | concurrency: 6 | group: ${{ github.workflow }}-${{ github.head_ref }} 7 | cancel-in-progress: true 8 | jobs: 9 | build: 10 | name: Build 11 | runs-on: ubuntu-latest 12 | timeout-minutes: 3 13 | steps: 14 | - name: Check out code into the Go module directory 15 | uses: actions/checkout@v4 16 | 17 | - name: Set up Go 18 | uses: actions/setup-go@v5 19 | with: 20 | go-version-file: ./go.mod 21 | 22 | - run: make bootstrap-tools 23 | - run: make lint 24 | - run: make cover 25 | 26 | - uses: k1LoW/octocov-action@v1 27 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - "!*" 6 | tags: 7 | - "v*.*.*" 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.head_ref }} 10 | cancel-in-progress: true 11 | permissions: 12 | contents: write 13 | jobs: 14 | build: 15 | name: Build 16 | runs-on: ubuntu-latest 17 | timeout-minutes: 3 18 | steps: 19 | - name: Check out code into the Go module directory 20 | uses: actions/checkout@v4 21 | 22 | - name: Set up Go 23 | uses: actions/setup-go@v5 24 | with: 25 | go-version-file: ./go.mod 26 | 27 | - name: Run GoReleaser 28 | uses: goreleaser/goreleaser-action@v6 29 | with: 30 | distribution: goreleaser 31 | version: latest 32 | args: release --clean 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | bin/ 17 | coverage.txt 18 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | skip-dirs: 3 | - bin 4 | - .github 5 | - tools 6 | 7 | linters-settings: 8 | govet: 9 | check-shadowing: true 10 | 11 | linters: 12 | enable-all: true 13 | disable: 14 | - cyclop 15 | - dogsled 16 | - dupl 17 | - exhaustive 18 | - exhaustivestruct 19 | - exhaustruct 20 | - funlen 21 | - gocognit 22 | - godox 23 | - gomnd 24 | - interfacer 25 | - ireturn 26 | - maintidx 27 | - mnd 28 | - nlreturn 29 | - nosnakecase 30 | - paralleltest 31 | - testpackage 32 | - wsl 33 | - depguard 34 | - perfsprint 35 | - scopelint 36 | - golint 37 | - structcheck 38 | - maligned 39 | - ifshort 40 | - varcheck 41 | - deadcode 42 | 43 | issues: 44 | exclude-rules: 45 | - text: "shadow: declaration of \"err\"" 46 | linters: ["govet"] 47 | - text: "use of `fmt.Print" 48 | linters: ["forbidigo"] 49 | - text: "is too short for the scope of its usage" 50 | linters: ["varnamelen"] 51 | - text: "has complex nested blocks" 52 | linters: ["nestif"] 53 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | builds: 2 | - env: 3 | - CGO_ENABLED=0 4 | goos: 5 | - linux 6 | - darwin 7 | - windows 8 | goarch: 9 | - 386 10 | - amd64 11 | - arm64 12 | main: ./cmd/yaml-diff/main.go 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 sters 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | export GOBIN := $(PWD)/bin 3 | export PATH := $(GOBIN):$(PATH) 4 | 5 | TOOLS=$(shell cat tools/tools.go | egrep '^\s_ ' | awk '{ print $$2 }') 6 | 7 | .PHONY: bootstrap-tools 8 | bootstrap-tools: 9 | @echo "Installing: " $(TOOLS) 10 | @cd tools && go install $(TOOLS) 11 | 12 | .PHONY: run 13 | run: 14 | go run main.go $(ARGS) 15 | 16 | .PHONY: lint 17 | lint: 18 | $(GOBIN)/golangci-lint run -v ./... 19 | 20 | .PHONY: lint-fix 21 | lint-fix: 22 | $(GOBIN)/golangci-lint run --fix -v ./... 23 | 24 | .PHONY: test 25 | test: 26 | go test -v -race ./... 27 | 28 | .PHONY: cover 29 | cover: 30 | go test -v -race -coverpkg=./... -coverprofile=coverage.out ./... 31 | 32 | .PHONY: tidy 33 | tidy: 34 | go mod tidy 35 | cd tools && go mod tidy 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # yaml-diff 2 | 3 | [![go](https://github.com/sters/yaml-diff/workflows/Go/badge.svg)](https://github.com/sters/yaml-diff/actions?query=workflow%3AGo) 4 | [![codecov](https://codecov.io/gh/sters/yaml-diff/branch/main/graph/badge.svg)](https://codecov.io/gh/sters/yaml-diff) 5 | [![go-report](https://goreportcard.com/badge/github.com/sters/yaml-diff)](https://goreportcard.com/report/github.com/sters/yaml-diff) 6 | 7 | ## Usage 8 | 9 | ``` 10 | go install github.com/sters/yaml-diff/cmd/yaml-diff@latest 11 | ``` 12 | or download from [Releases](https://github.com/sters/yaml-diff/releases). 13 | 14 | ``` 15 | yaml-diff path/to/foo.yaml path/to/bar.yaml 16 | ``` 17 | 18 | If the given yaml has a [`---` separated structure](https://yaml.org/spec/1.2.2/#22-structures), then the two yaml's will get all the differences in their respective structures. The one with the smallest difference is considered to be the same structure and the difference is displayed. 19 | 20 | The result structure is the same as based or target yaml but format (includes map fields order) is different. 21 | 22 | ## Example 23 | 24 |
You can try example directory. 25 | 26 | ```text 27 | $ go run cmd/yaml-diff/main.go example/a.yaml example/b.yaml 28 | --- example/a.yaml 29 | +++ example/b.yaml 30 | 31 | apiVersion: "v1" 32 | kind: "Service" 33 | metadata: 34 | name: "my-service" 35 | spec: 36 | selector: 37 | app: "MyApp" 38 | ports: 39 | - 40 | protocol: "TCP" 41 | - port: 80 42 | + port: 8080 43 | targetPort: 9376 44 | 45 | apiVersion: "apps/v1" 46 | kind: "Deployment" 47 | metadata: 48 | name: "app-deployment" 49 | labels: 50 | app: "MyApp" 51 | spec: 52 | - replicas: 3 53 | + replicas: 10 54 | selector: 55 | matchLabels: 56 | app: "MyApp" 57 | template: 58 | metadata: 59 | labels: 60 | app: "MyApp" 61 | spec: 62 | containers: 63 | - 64 | name: "app" 65 | - image: "my-app:1.0.0" 66 | + image: "my-app:1.1.0" 67 | ports: 68 | - 69 | containerPort: 9376 70 | 71 | - foo: "missing-in-b" 72 | 73 | this: 74 | is: 75 | the: "same" 76 | - empty: 77 | 78 | + bar: 79 | + - "missing in a.yaml" 80 | 81 | + baz: 82 | + - "missing in a.yaml" 83 | ``` 84 | 85 | ```text 86 | $ go run cmd/yaml-diff/main.go --ignore-empty-fields example/a.yaml example/b.yaml 87 | --- example/a.yaml 88 | +++ example/b.yaml 89 | 90 | apiVersion: "v1" 91 | kind: "Service" 92 | metadata: 93 | name: "my-service" 94 | spec: 95 | selector: 96 | app: "MyApp" 97 | ports: 98 | - 99 | protocol: "TCP" 100 | - port: 80 101 | + port: 8080 102 | targetPort: 9376 103 | 104 | apiVersion: "apps/v1" 105 | kind: "Deployment" 106 | metadata: 107 | name: "app-deployment" 108 | labels: 109 | app: "MyApp" 110 | spec: 111 | - replicas: 3 112 | + replicas: 10 113 | selector: 114 | matchLabels: 115 | app: "MyApp" 116 | template: 117 | metadata: 118 | labels: 119 | app: "MyApp" 120 | spec: 121 | containers: 122 | - 123 | name: "app" 124 | - image: "my-app:1.0.0" 125 | + image: "my-app:1.1.0" 126 | ports: 127 | - 128 | containerPort: 9376 129 | 130 | - foo: "missing-in-b" 131 | 132 | this: 133 | is: 134 | the: "same" 135 | empty: 136 | 137 | + bar: 138 | + - "missing in a.yaml" 139 | 140 | + baz: 141 | + - "missing in a.yaml" 142 | ``` 143 | 144 |
145 | -------------------------------------------------------------------------------- /cmd/yaml-diff/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io" 7 | "log" 8 | "os" 9 | 10 | "github.com/sters/yaml-diff/yamldiff" 11 | ) 12 | 13 | func main() { 14 | ignoreEmptyFields := flag.Bool("ignore-empty-fields", false, "Ignore empty field") 15 | ignoreZeroFields := flag.Bool("ignore-zero-fields", false, "Ignore zero field") 16 | flag.Parse() 17 | 18 | args := flag.Args() 19 | if len(args) != 2 { 20 | fmt.Println("Usage: yaml-diff file1 file2") 21 | os.Exit(1) 22 | } 23 | file1 := args[0] 24 | file2 := args[1] 25 | 26 | yamls1, err := yamldiff.Load(load(file1)) 27 | if err != nil { 28 | fmt.Fprintf(os.Stderr, "%+v", err) 29 | } 30 | 31 | yamls2, err := yamldiff.Load(load(file2)) 32 | if err != nil { 33 | fmt.Fprintf(os.Stderr, "%+v", err) 34 | } 35 | 36 | opts := []yamldiff.DoOptionFunc{} 37 | if *ignoreEmptyFields { 38 | opts = append(opts, yamldiff.EmptyAsNull()) 39 | } 40 | if *ignoreZeroFields { 41 | opts = append(opts, yamldiff.ZeroAsNull()) 42 | } 43 | 44 | fmt.Printf("--- %s\n+++ %s\n\n", file1, file2) 45 | for _, diff := range yamldiff.Do(yamls1, yamls2, opts...) { 46 | fmt.Println(diff.Dump()) 47 | } 48 | 49 | fmt.Print() 50 | } 51 | 52 | func load(f string) string { 53 | file, err := os.Open(f) 54 | defer func() { _ = file.Close() }() 55 | if err != nil { 56 | log.Printf("%+v, %s", err, f) 57 | 58 | return "" 59 | } 60 | 61 | b, err := io.ReadAll(file) 62 | if err != nil { 63 | log.Printf("%+v, %s", err, f) 64 | 65 | return "" 66 | } 67 | 68 | return string(b) 69 | } 70 | -------------------------------------------------------------------------------- /example/a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: my-service 6 | spec: 7 | selector: 8 | app: MyApp 9 | ports: 10 | - protocol: TCP 11 | port: 80 12 | targetPort: 9376 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: app-deployment 18 | labels: 19 | app: MyApp 20 | spec: 21 | replicas: 3 22 | selector: 23 | matchLabels: 24 | app: MyApp 25 | template: 26 | metadata: 27 | labels: 28 | app: MyApp 29 | spec: 30 | containers: 31 | - name: app 32 | image: my-app:1.0.0 33 | ports: 34 | - containerPort: 9376 35 | --- 36 | foo: missing-in-b 37 | --- 38 | this: 39 | is: 40 | the: same 41 | empty: 42 | -------------------------------------------------------------------------------- /example/b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | metadata: 3 | name: my-service 4 | spec: 5 | ports: 6 | - protocol: TCP 7 | targetPort: 9376 8 | port: 8080 9 | selector: 10 | app: MyApp 11 | apiVersion: v1 12 | kind: Service 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | spec: 17 | selector: 18 | matchLabels: 19 | app: MyApp 20 | replicas: 10 21 | template: 22 | metadata: 23 | labels: 24 | app: MyApp 25 | spec: 26 | containers: 27 | - name: app 28 | ports: 29 | - containerPort: 9376 30 | image: my-app:1.1.0 31 | metadata: 32 | name: app-deployment 33 | labels: 34 | app: MyApp 35 | --- 36 | bar: 37 | - missing in a.yaml 38 | --- 39 | baz: 40 | - missing in a.yaml 41 | --- 42 | this: 43 | is: 44 | the: same 45 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sters/yaml-diff 2 | 3 | go 1.23 4 | 5 | require ( 6 | github.com/goccy/go-yaml v1.17.1 7 | github.com/stretchr/testify v1.10.0 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/kr/text v0.2.0 // indirect 13 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect 14 | github.com/pmezard/go-difflib v1.0.0 // indirect 15 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect 16 | gopkg.in/yaml.v3 v3.0.1 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY= 5 | github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= 6 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 7 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 8 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 9 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 10 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= 11 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 12 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 13 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 14 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 15 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 16 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 17 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= 18 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 19 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 20 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 21 | -------------------------------------------------------------------------------- /tools/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sters/yaml-diff/tools 2 | 3 | go 1.23.3 4 | 5 | require github.com/golangci/golangci-lint v1.62.2 6 | 7 | require ( 8 | 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect 9 | 4d63.com/gochecknoglobals v0.2.1 // indirect 10 | github.com/4meepo/tagalign v1.3.4 // indirect 11 | github.com/Abirdcfly/dupword v0.1.3 // indirect 12 | github.com/Antonboom/errname v1.0.0 // indirect 13 | github.com/Antonboom/nilnil v1.0.0 // indirect 14 | github.com/Antonboom/testifylint v1.5.2 // indirect 15 | github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect 16 | github.com/Crocmagnon/fatcontext v0.5.3 // indirect 17 | github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect 18 | github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect 19 | github.com/Masterminds/semver/v3 v3.3.0 // indirect 20 | github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect 21 | github.com/alecthomas/go-check-sumtype v0.2.0 // indirect 22 | github.com/alexkohler/nakedret/v2 v2.0.5 // indirect 23 | github.com/alexkohler/prealloc v1.0.0 // indirect 24 | github.com/alingse/asasalint v0.0.11 // indirect 25 | github.com/ashanbrown/forbidigo v1.6.0 // indirect 26 | github.com/ashanbrown/makezero v1.1.1 // indirect 27 | github.com/beorn7/perks v1.0.1 // indirect 28 | github.com/bkielbasa/cyclop v1.2.3 // indirect 29 | github.com/blizzy78/varnamelen v0.8.0 // indirect 30 | github.com/bombsimon/wsl/v4 v4.4.1 // indirect 31 | github.com/breml/bidichk v0.3.2 // indirect 32 | github.com/breml/errchkjson v0.4.0 // indirect 33 | github.com/butuzov/ireturn v0.3.0 // indirect 34 | github.com/butuzov/mirror v1.2.0 // indirect 35 | github.com/catenacyber/perfsprint v0.7.1 // indirect 36 | github.com/ccojocar/zxcvbn-go v1.0.2 // indirect 37 | github.com/cespare/xxhash/v2 v2.1.2 // indirect 38 | github.com/charithe/durationcheck v0.0.10 // indirect 39 | github.com/chavacava/garif v0.1.0 // indirect 40 | github.com/ckaznocha/intrange v0.2.1 // indirect 41 | github.com/curioswitch/go-reassign v0.2.0 // indirect 42 | github.com/daixiang0/gci v0.13.5 // indirect 43 | github.com/davecgh/go-spew v1.1.1 // indirect 44 | github.com/denis-tingaikin/go-header v0.5.0 // indirect 45 | github.com/ettle/strcase v0.2.0 // indirect 46 | github.com/fatih/color v1.18.0 // indirect 47 | github.com/fatih/structtag v1.2.0 // indirect 48 | github.com/firefart/nonamedreturns v1.0.5 // indirect 49 | github.com/fsnotify/fsnotify v1.5.4 // indirect 50 | github.com/fzipp/gocyclo v0.6.0 // indirect 51 | github.com/ghostiam/protogetter v0.3.8 // indirect 52 | github.com/go-critic/go-critic v0.11.5 // indirect 53 | github.com/go-toolsmith/astcast v1.1.0 // indirect 54 | github.com/go-toolsmith/astcopy v1.1.0 // indirect 55 | github.com/go-toolsmith/astequal v1.2.0 // indirect 56 | github.com/go-toolsmith/astfmt v1.1.0 // indirect 57 | github.com/go-toolsmith/astp v1.1.0 // indirect 58 | github.com/go-toolsmith/strparse v1.1.0 // indirect 59 | github.com/go-toolsmith/typep v1.1.0 // indirect 60 | github.com/go-viper/mapstructure/v2 v2.2.1 // indirect 61 | github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect 62 | github.com/gobwas/glob v0.2.3 // indirect 63 | github.com/gofrs/flock v0.12.1 // indirect 64 | github.com/golang/protobuf v1.5.3 // indirect 65 | github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect 66 | github.com/golangci/go-printf-func-name v0.1.0 // indirect 67 | github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 // indirect 68 | github.com/golangci/misspell v0.6.0 // indirect 69 | github.com/golangci/modinfo v0.3.4 // indirect 70 | github.com/golangci/plugin-module-register v0.1.1 // indirect 71 | github.com/golangci/revgrep v0.5.3 // indirect 72 | github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect 73 | github.com/google/go-cmp v0.6.0 // indirect 74 | github.com/gordonklaus/ineffassign v0.1.0 // indirect 75 | github.com/gostaticanalysis/analysisutil v0.7.1 // indirect 76 | github.com/gostaticanalysis/comment v1.4.2 // indirect 77 | github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect 78 | github.com/gostaticanalysis/nilerr v0.1.1 // indirect 79 | github.com/hashicorp/go-version v1.7.0 // indirect 80 | github.com/hashicorp/hcl v1.0.0 // indirect 81 | github.com/hexops/gotextdiff v1.0.3 // indirect 82 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 83 | github.com/jgautheron/goconst v1.7.1 // indirect 84 | github.com/jingyugao/rowserrcheck v1.1.1 // indirect 85 | github.com/jjti/go-spancheck v0.6.2 // indirect 86 | github.com/julz/importas v0.1.0 // indirect 87 | github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect 88 | github.com/kisielk/errcheck v1.8.0 // indirect 89 | github.com/kkHAIKE/contextcheck v1.1.5 // indirect 90 | github.com/kulti/thelper v0.6.3 // indirect 91 | github.com/kunwardeep/paralleltest v1.0.10 // indirect 92 | github.com/kyoh86/exportloopref v0.1.11 // indirect 93 | github.com/lasiar/canonicalheader v1.1.2 // indirect 94 | github.com/ldez/gomoddirectives v0.2.4 // indirect 95 | github.com/ldez/tagliatelle v0.5.0 // indirect 96 | github.com/leonklingele/grouper v1.1.2 // indirect 97 | github.com/macabu/inamedparam v0.1.3 // indirect 98 | github.com/magiconair/properties v1.8.6 // indirect 99 | github.com/maratori/testableexamples v1.0.0 // indirect 100 | github.com/maratori/testpackage v1.1.1 // indirect 101 | github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect 102 | github.com/mattn/go-colorable v0.1.13 // indirect 103 | github.com/mattn/go-isatty v0.0.20 // indirect 104 | github.com/mattn/go-runewidth v0.0.16 // indirect 105 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 106 | github.com/mgechev/revive v1.5.1 // indirect 107 | github.com/mitchellh/go-homedir v1.1.0 // indirect 108 | github.com/mitchellh/mapstructure v1.5.0 // indirect 109 | github.com/moricho/tparallel v0.3.2 // indirect 110 | github.com/nakabonne/nestif v0.3.1 // indirect 111 | github.com/nishanths/exhaustive v0.12.0 // indirect 112 | github.com/nishanths/predeclared v0.2.2 // indirect 113 | github.com/nunnatsa/ginkgolinter v0.18.3 // indirect 114 | github.com/olekukonko/tablewriter v0.0.5 // indirect 115 | github.com/pelletier/go-toml v1.9.5 // indirect 116 | github.com/pelletier/go-toml/v2 v2.2.3 // indirect 117 | github.com/pmezard/go-difflib v1.0.0 // indirect 118 | github.com/polyfloyd/go-errorlint v1.7.0 // indirect 119 | github.com/prometheus/client_golang v1.12.1 // indirect 120 | github.com/prometheus/client_model v0.2.0 // indirect 121 | github.com/prometheus/common v0.32.1 // indirect 122 | github.com/prometheus/procfs v0.7.3 // indirect 123 | github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect 124 | github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect 125 | github.com/quasilyte/gogrep v0.5.0 // indirect 126 | github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect 127 | github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect 128 | github.com/raeperd/recvcheck v0.1.2 // indirect 129 | github.com/rivo/uniseg v0.4.7 // indirect 130 | github.com/rogpeppe/go-internal v1.13.1 // indirect 131 | github.com/ryancurrah/gomodguard v1.3.5 // indirect 132 | github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect 133 | github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect 134 | github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect 135 | github.com/sashamelentyev/interfacebloat v1.1.0 // indirect 136 | github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect 137 | github.com/securego/gosec/v2 v2.21.4 // indirect 138 | github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect 139 | github.com/sirupsen/logrus v1.9.3 // indirect 140 | github.com/sivchari/containedctx v1.0.3 // indirect 141 | github.com/sivchari/tenv v1.12.1 // indirect 142 | github.com/sonatard/noctx v0.1.0 // indirect 143 | github.com/sourcegraph/go-diff v0.7.0 // indirect 144 | github.com/spf13/afero v1.11.0 // indirect 145 | github.com/spf13/cast v1.5.0 // indirect 146 | github.com/spf13/cobra v1.8.1 // indirect 147 | github.com/spf13/jwalterweatherman v1.1.0 // indirect 148 | github.com/spf13/pflag v1.0.5 // indirect 149 | github.com/spf13/viper v1.12.0 // indirect 150 | github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect 151 | github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect 152 | github.com/stretchr/objx v0.5.2 // indirect 153 | github.com/stretchr/testify v1.10.0 // indirect 154 | github.com/subosito/gotenv v1.4.1 // indirect 155 | github.com/tdakkota/asciicheck v0.2.0 // indirect 156 | github.com/tetafro/godot v1.4.18 // indirect 157 | github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect 158 | github.com/timonwong/loggercheck v0.10.1 // indirect 159 | github.com/tomarrell/wrapcheck/v2 v2.9.0 // indirect 160 | github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect 161 | github.com/ultraware/funlen v0.1.0 // indirect 162 | github.com/ultraware/whitespace v0.1.1 // indirect 163 | github.com/uudashr/gocognit v1.1.3 // indirect 164 | github.com/uudashr/iface v1.2.1 // indirect 165 | github.com/xen0n/gosmopolitan v1.2.2 // indirect 166 | github.com/yagipy/maintidx v1.0.0 // indirect 167 | github.com/yeya24/promlinter v0.3.0 // indirect 168 | github.com/ykadowak/zerologlint v0.1.5 // indirect 169 | gitlab.com/bosi/decorder v0.4.2 // indirect 170 | go-simpler.org/musttag v0.13.0 // indirect 171 | go-simpler.org/sloglint v0.7.2 // indirect 172 | go.uber.org/atomic v1.7.0 // indirect 173 | go.uber.org/automaxprocs v1.6.0 // indirect 174 | go.uber.org/multierr v1.6.0 // indirect 175 | go.uber.org/zap v1.24.0 // indirect 176 | golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect 177 | golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f // indirect 178 | golang.org/x/mod v0.22.0 // indirect 179 | golang.org/x/sync v0.9.0 // indirect 180 | golang.org/x/sys v0.27.0 // indirect 181 | golang.org/x/text v0.18.0 // indirect 182 | golang.org/x/tools v0.27.0 // indirect 183 | google.golang.org/protobuf v1.34.2 // indirect 184 | gopkg.in/ini.v1 v1.67.0 // indirect 185 | gopkg.in/yaml.v2 v2.4.0 // indirect 186 | gopkg.in/yaml.v3 v3.0.1 // indirect 187 | honnef.co/go/tools v0.5.1 // indirect 188 | mvdan.cc/gofumpt v0.7.0 // indirect 189 | mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect 190 | ) 191 | -------------------------------------------------------------------------------- /tools/go.sum: -------------------------------------------------------------------------------- 1 | 4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= 2 | 4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= 3 | 4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= 4 | 4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= 5 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 6 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 7 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 8 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 9 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 10 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 11 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 12 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 13 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 14 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 15 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 16 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 17 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 18 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 19 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 20 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 21 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 22 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 23 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 24 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 25 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 26 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 27 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 28 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 29 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 30 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 31 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 32 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 33 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 34 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 35 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 36 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 37 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 38 | github.com/4meepo/tagalign v1.3.4 h1:P51VcvBnf04YkHzjfclN6BbsopfJR5rxs1n+5zHt+w8= 39 | github.com/4meepo/tagalign v1.3.4/go.mod h1:M+pnkHH2vG8+qhE5bVc/zeP7HS/j910Fwa9TUSyZVI0= 40 | github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= 41 | github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= 42 | github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= 43 | github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= 44 | github.com/Antonboom/nilnil v1.0.0 h1:n+v+B12dsE5tbAqRODXmEKfZv9j2KcTBrp+LkoM4HZk= 45 | github.com/Antonboom/nilnil v1.0.0/go.mod h1:fDJ1FSFoLN6yoG65ANb1WihItf6qt9PJVTn/s2IrcII= 46 | github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= 47 | github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= 48 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 49 | github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= 50 | github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= 51 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 52 | github.com/Crocmagnon/fatcontext v0.5.3 h1:zCh/wjc9oyeF+Gmp+V60wetm8ph2tlsxocgg/J0hOps= 53 | github.com/Crocmagnon/fatcontext v0.5.3/go.mod h1:XoCQYY1J+XTfyv74qLXvNw4xFunr3L1wkopIIKG7wGM= 54 | github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= 55 | github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= 56 | github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU= 57 | github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao= 58 | github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= 59 | github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 60 | github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= 61 | github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= 62 | github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= 63 | github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= 64 | github.com/alecthomas/go-check-sumtype v0.2.0 h1:Bo+e4DFf3rs7ME9w/0SU/g6nmzJaphduP8Cjiz0gbwY= 65 | github.com/alecthomas/go-check-sumtype v0.2.0/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= 66 | github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= 67 | github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= 68 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 69 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 70 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 71 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 72 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 73 | github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= 74 | github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= 75 | github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= 76 | github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= 77 | github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= 78 | github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= 79 | github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= 80 | github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= 81 | github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= 82 | github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= 83 | github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 84 | github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 85 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 86 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 87 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 88 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 89 | github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= 90 | github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= 91 | github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= 92 | github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= 93 | github.com/bombsimon/wsl/v4 v4.4.1 h1:jfUaCkN+aUpobrMO24zwyAMwMAV5eSziCkOKEauOLdw= 94 | github.com/bombsimon/wsl/v4 v4.4.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= 95 | github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= 96 | github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= 97 | github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= 98 | github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= 99 | github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0= 100 | github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA= 101 | github.com/butuzov/mirror v1.2.0 h1:9YVK1qIjNspaqWutSv8gsge2e/Xpq1eqEkslEUHy5cs= 102 | github.com/butuzov/mirror v1.2.0/go.mod h1:DqZZDtzm42wIAIyHXeN8W/qb1EPlb9Qn/if9icBOpdQ= 103 | github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc= 104 | github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= 105 | github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= 106 | github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= 107 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 108 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 109 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= 110 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 111 | github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= 112 | github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= 113 | github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= 114 | github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= 115 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 116 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 117 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 118 | github.com/ckaznocha/intrange v0.2.1 h1:M07spnNEQoALOJhwrImSrJLaxwuiQK+hA2DeajBlwYk= 119 | github.com/ckaznocha/intrange v0.2.1/go.mod h1:7NEhVyf8fzZO5Ds7CRaqPEm52Ut83hsTiL5zbER/HYk= 120 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 121 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 122 | github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 123 | github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= 124 | github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= 125 | github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= 126 | github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= 127 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 128 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 129 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 130 | github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= 131 | github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= 132 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 133 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 134 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 135 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 136 | github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= 137 | github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= 138 | github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= 139 | github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= 140 | github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= 141 | github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= 142 | github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= 143 | github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= 144 | github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= 145 | github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= 146 | github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= 147 | github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= 148 | github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= 149 | github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= 150 | github.com/ghostiam/protogetter v0.3.8 h1:LYcXbYvybUyTIxN2Mj9h6rHrDZBDwZloPoKctWrFyJY= 151 | github.com/ghostiam/protogetter v0.3.8/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= 152 | github.com/go-critic/go-critic v0.11.5 h1:TkDTOn5v7EEngMxu8KbuFqFR43USaaH8XRJLz1jhVYA= 153 | github.com/go-critic/go-critic v0.11.5/go.mod h1:wu6U7ny9PiaHaZHcvMDmdysMqvDem162Rh3zWTrqk8M= 154 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 155 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 156 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 157 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 158 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 159 | github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 160 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 161 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 162 | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 163 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 164 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 165 | github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= 166 | github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= 167 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 168 | github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= 169 | github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= 170 | github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= 171 | github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= 172 | github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= 173 | github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= 174 | github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= 175 | github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= 176 | github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= 177 | github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= 178 | github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= 179 | github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= 180 | github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= 181 | github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= 182 | github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= 183 | github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= 184 | github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= 185 | github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= 186 | github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= 187 | github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= 188 | github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= 189 | github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= 190 | github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= 191 | github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= 192 | github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= 193 | github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= 194 | github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= 195 | github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= 196 | github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= 197 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 198 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 199 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 200 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 201 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 202 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 203 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 204 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 205 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 206 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 207 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 208 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 209 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 210 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 211 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 212 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 213 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 214 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 215 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 216 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 217 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 218 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 219 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 220 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 221 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 222 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 223 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 224 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 225 | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= 226 | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 227 | github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= 228 | github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= 229 | github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= 230 | github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= 231 | github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 h1:/1322Qns6BtQxUZDTAT4SdcoxknUki7IAoK4SAXr8ME= 232 | github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9/go.mod h1:Oesb/0uFAyWoaw1U1qS5zyjCg5NP9C9iwjnI4tIsXEE= 233 | github.com/golangci/golangci-lint v1.62.2 h1:b8K5K9PN+rZN1+mKLtsZHz2XXS9aYKzQ9i25x3Qnxxw= 234 | github.com/golangci/golangci-lint v1.62.2/go.mod h1:ILWWyeFUrctpHVGMa1dg2xZPKoMUTc5OIMgW7HZr34g= 235 | github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= 236 | github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= 237 | github.com/golangci/modinfo v0.3.4 h1:oU5huX3fbxqQXdfspamej74DFX0kyGLkw1ppvXoJ8GA= 238 | github.com/golangci/modinfo v0.3.4/go.mod h1:wytF1M5xl9u0ij8YSvhkEVPP3M5Mc7XLl1pxH3B2aUM= 239 | github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= 240 | github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= 241 | github.com/golangci/revgrep v0.5.3 h1:3tL7c1XBMtWHHqVpS5ChmiAAoe4PF/d5+ULzV9sLAzs= 242 | github.com/golangci/revgrep v0.5.3/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= 243 | github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= 244 | github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= 245 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 246 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 247 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 248 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 249 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 250 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 251 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 252 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 253 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 254 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 255 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 256 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 257 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 258 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 259 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 260 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 261 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 262 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 263 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 264 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 265 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 266 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 267 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 268 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 269 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 270 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 271 | github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= 272 | github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= 273 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 274 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 275 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 276 | github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= 277 | github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= 278 | github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= 279 | github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= 280 | github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= 281 | github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= 282 | github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= 283 | github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= 284 | github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= 285 | github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= 286 | github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= 287 | github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= 288 | github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= 289 | github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= 290 | github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 291 | github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= 292 | github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 293 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 294 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 295 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 296 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 297 | github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= 298 | github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= 299 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 300 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 301 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 302 | github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= 303 | github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= 304 | github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= 305 | github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= 306 | github.com/jjti/go-spancheck v0.6.2 h1:iYtoxqPMzHUPp7St+5yA8+cONdyXD3ug6KK15n7Pklk= 307 | github.com/jjti/go-spancheck v0.6.2/go.mod h1:+X7lvIrR5ZdUTkxFYqzJ0abr8Sb5LOo80uOhWNqIrYA= 308 | github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 309 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 310 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 311 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 312 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 313 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 314 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 315 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 316 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 317 | github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= 318 | github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= 319 | github.com/karamaru-alpha/copyloopvar v1.1.0 h1:x7gNyKcC2vRBO1H2Mks5u1VxQtYvFiym7fCjIP8RPos= 320 | github.com/karamaru-alpha/copyloopvar v1.1.0/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k= 321 | github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= 322 | github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= 323 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 324 | github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg= 325 | github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA= 326 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 327 | github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 328 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 329 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 330 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 331 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 332 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 333 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 334 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 335 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 336 | github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= 337 | github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= 338 | github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= 339 | github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= 340 | github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= 341 | github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= 342 | github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= 343 | github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= 344 | github.com/ldez/gomoddirectives v0.2.4 h1:j3YjBIjEBbqZ0NKtBNzr8rtMHTOrLPeiwTkfUJZ3alg= 345 | github.com/ldez/gomoddirectives v0.2.4/go.mod h1:oWu9i62VcQDYp9EQ0ONTfqLNh+mDLWWDO+SO0qSQw5g= 346 | github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= 347 | github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= 348 | github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= 349 | github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= 350 | github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= 351 | github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= 352 | github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= 353 | github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 354 | github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= 355 | github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= 356 | github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= 357 | github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= 358 | github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= 359 | github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= 360 | github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= 361 | github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= 362 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 363 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 364 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 365 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 366 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 367 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 368 | github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= 369 | github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 370 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 371 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 372 | github.com/mgechev/revive v1.5.1 h1:hE+QPeq0/wIzJwOphdVyUJ82njdd8Khp4fUIHGZHW3M= 373 | github.com/mgechev/revive v1.5.1/go.mod h1:lC9AhkJIBs5zwx8wkudyHrU+IJkrEKmpCmGMnIJPk4o= 374 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 375 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 376 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 377 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 378 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 379 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 380 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 381 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 382 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 383 | github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= 384 | github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= 385 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 386 | github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 387 | github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= 388 | github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= 389 | github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= 390 | github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= 391 | github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= 392 | github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= 393 | github.com/nunnatsa/ginkgolinter v0.18.3 h1:WgS7X3zzmni3vwHSBhvSgqrRgUecN6PQUcfB0j1noDw= 394 | github.com/nunnatsa/ginkgolinter v0.18.3/go.mod h1:BE1xyB/PNtXXG1azrvrqJW5eFH0hSRylNzFy8QHPwzs= 395 | github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= 396 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 397 | github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= 398 | github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= 399 | github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= 400 | github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= 401 | github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= 402 | github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= 403 | github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= 404 | github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= 405 | github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= 406 | github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= 407 | github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= 408 | github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= 409 | github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 410 | github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= 411 | github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= 412 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 413 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 414 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 415 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 416 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 417 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 418 | github.com/polyfloyd/go-errorlint v1.7.0 h1:Zp6lzCK4hpBDj8y8a237YK4EPrMXQWvOe3nGoH4pFrU= 419 | github.com/polyfloyd/go-errorlint v1.7.0/go.mod h1:dGWKu85mGHnegQ2SWpEybFityCg3j7ZbwsVUxAOk9gY= 420 | github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= 421 | github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= 422 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 423 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 424 | github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 425 | github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= 426 | github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= 427 | github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= 428 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 429 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 430 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 431 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 432 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 433 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 434 | github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 435 | github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= 436 | github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= 437 | github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= 438 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 439 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 440 | github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 441 | github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 442 | github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= 443 | github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 444 | github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= 445 | github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= 446 | github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= 447 | github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= 448 | github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= 449 | github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= 450 | github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= 451 | github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= 452 | github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= 453 | github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= 454 | github.com/raeperd/recvcheck v0.1.2 h1:SjdquRsRXJc26eSonWIo8b7IMtKD3OAT2Lb5G3ZX1+4= 455 | github.com/raeperd/recvcheck v0.1.2/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU= 456 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 457 | github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 458 | github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 459 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 460 | github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 461 | github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 462 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 463 | github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= 464 | github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= 465 | github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= 466 | github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= 467 | github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= 468 | github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= 469 | github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= 470 | github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= 471 | github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= 472 | github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= 473 | github.com/sashamelentyev/usestdlibvars v1.27.0 h1:t/3jZpSXtRPRf2xr0m63i32ZrusyurIGT9E5wAvXQnI= 474 | github.com/sashamelentyev/usestdlibvars v1.27.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= 475 | github.com/securego/gosec/v2 v2.21.4 h1:Le8MSj0PDmOnHJgUATjD96PaXRvCpKC+DGJvwyy0Mlk= 476 | github.com/securego/gosec/v2 v2.21.4/go.mod h1:Jtb/MwRQfRxCXyCm1rfM1BEiiiTfUOdyzzAhlr6lUTA= 477 | github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= 478 | github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= 479 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= 480 | github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= 481 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 482 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 483 | github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 484 | github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= 485 | github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 486 | github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= 487 | github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= 488 | github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= 489 | github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= 490 | github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= 491 | github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= 492 | github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= 493 | github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= 494 | github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= 495 | github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= 496 | github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= 497 | github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= 498 | github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= 499 | github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 500 | github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= 501 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 502 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 503 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 504 | github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= 505 | github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= 506 | github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= 507 | github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= 508 | github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= 509 | github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= 510 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 511 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 512 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 513 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 514 | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= 515 | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 516 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 517 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 518 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 519 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 520 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 521 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 522 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 523 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 524 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 525 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 526 | github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= 527 | github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= 528 | github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= 529 | github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= 530 | github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= 531 | github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= 532 | github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= 533 | github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= 534 | github.com/tetafro/godot v1.4.18 h1:ouX3XGiziKDypbpXqShBfnNLTSjR8r3/HVzrtJ+bHlI= 535 | github.com/tetafro/godot v1.4.18/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= 536 | github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= 537 | github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= 538 | github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= 539 | github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= 540 | github.com/tomarrell/wrapcheck/v2 v2.9.0 h1:801U2YCAjLhdN8zhZ/7tdjB3EnAoRlJHt/s+9hijLQ4= 541 | github.com/tomarrell/wrapcheck/v2 v2.9.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= 542 | github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= 543 | github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= 544 | github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= 545 | github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= 546 | github.com/ultraware/whitespace v0.1.1 h1:bTPOGejYFulW3PkcrqkeQwOd6NKOOXvmGD9bo/Gk8VQ= 547 | github.com/ultraware/whitespace v0.1.1/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= 548 | github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM= 549 | github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U= 550 | github.com/uudashr/iface v1.2.1 h1:vHHyzAUmWZ64Olq6NZT3vg/z1Ws56kyPdBOd5kTXDF8= 551 | github.com/uudashr/iface v1.2.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= 552 | github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= 553 | github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= 554 | github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= 555 | github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= 556 | github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= 557 | github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4= 558 | github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= 559 | github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= 560 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 561 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 562 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 563 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 564 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 565 | github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 566 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 567 | gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= 568 | gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= 569 | go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= 570 | go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= 571 | go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= 572 | go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= 573 | go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY= 574 | go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo= 575 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 576 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 577 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 578 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 579 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 580 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= 581 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 582 | go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= 583 | go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= 584 | go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= 585 | go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 586 | go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= 587 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 588 | go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= 589 | go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 590 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 591 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 592 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 593 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 594 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 595 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 596 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 597 | golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= 598 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 599 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 600 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 601 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 602 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 603 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 604 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 605 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 606 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 607 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 608 | golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= 609 | golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= 610 | golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= 611 | golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= 612 | golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f h1:WTyX8eCCyfdqiPYkRGm0MqElSfYFH3yR1+rl/mct9sA= 613 | golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= 614 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 615 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 616 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 617 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 618 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 619 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 620 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 621 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 622 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 623 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 624 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 625 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 626 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 627 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 628 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 629 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 630 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 631 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 632 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 633 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 634 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 635 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 636 | golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 637 | golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= 638 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 639 | golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= 640 | golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 641 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 642 | golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= 643 | golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 644 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 645 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 646 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 647 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 648 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 649 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 650 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 651 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 652 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 653 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 654 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 655 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 656 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 657 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 658 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 659 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 660 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 661 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 662 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 663 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 664 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 665 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 666 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 667 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 668 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 669 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 670 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 671 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 672 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 673 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 674 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 675 | golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 676 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 677 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 678 | golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= 679 | golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 680 | golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= 681 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 682 | golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= 683 | golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= 684 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 685 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 686 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 687 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 688 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 689 | golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 690 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 691 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 692 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 693 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 694 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 695 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 696 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 697 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 698 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 699 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 700 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 701 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 702 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 703 | golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= 704 | golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 705 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 706 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 707 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 708 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 709 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 710 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 711 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 712 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 713 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 714 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 715 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 716 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 717 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 718 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 719 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 720 | golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 721 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 722 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 723 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 724 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 725 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 726 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 727 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 728 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 729 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 730 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 731 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 732 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 733 | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 734 | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 735 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 736 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 737 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 738 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 739 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 740 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 741 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 742 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 743 | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 744 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 745 | golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 746 | golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 747 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 748 | golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 749 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 750 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 751 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 752 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 753 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 754 | golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 755 | golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 756 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 757 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 758 | golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= 759 | golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 760 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 761 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 762 | golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 763 | golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= 764 | golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= 765 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 766 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 767 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 768 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 769 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 770 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 771 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 772 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 773 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 774 | golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 775 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 776 | golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= 777 | golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 778 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 779 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 780 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 781 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 782 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 783 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 784 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 785 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 786 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 787 | golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 788 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 789 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 790 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 791 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 792 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 793 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 794 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 795 | golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 796 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 797 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 798 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 799 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 800 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 801 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 802 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 803 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 804 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 805 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 806 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 807 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 808 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 809 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 810 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 811 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 812 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 813 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 814 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 815 | golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 816 | golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 817 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 818 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 819 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 820 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 821 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 822 | golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 823 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 824 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 825 | golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 826 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 827 | golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 828 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 829 | golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= 830 | golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= 831 | golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 832 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 833 | golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= 834 | golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= 835 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 836 | golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= 837 | golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= 838 | golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= 839 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 840 | golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= 841 | golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= 842 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 843 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 844 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 845 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 846 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 847 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 848 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 849 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 850 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 851 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 852 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 853 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 854 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 855 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 856 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 857 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 858 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 859 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 860 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 861 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 862 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 863 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 864 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 865 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 866 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 867 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 868 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 869 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 870 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 871 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 872 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 873 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 874 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 875 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 876 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 877 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 878 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 879 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 880 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 881 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 882 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 883 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 884 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 885 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 886 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 887 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 888 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 889 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 890 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 891 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 892 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 893 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 894 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 895 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 896 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 897 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 898 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 899 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 900 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 901 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 902 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 903 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 904 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 905 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 906 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 907 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 908 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 909 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 910 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 911 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 912 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 913 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 914 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 915 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 916 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 917 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 918 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 919 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 920 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 921 | google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= 922 | google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 923 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 924 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 925 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 926 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 927 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 928 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 929 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 930 | gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= 931 | gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 932 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 933 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 934 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 935 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 936 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 937 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 938 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 939 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 940 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 941 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 942 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 943 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 944 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 945 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 946 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 947 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 948 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 949 | honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= 950 | honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= 951 | mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= 952 | mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= 953 | mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= 954 | mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= 955 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 956 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 957 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 958 | -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package tools 5 | 6 | import ( 7 | _ "github.com/golangci/golangci-lint/cmd/golangci-lint" 8 | ) 9 | -------------------------------------------------------------------------------- /yamldiff/diff.go: -------------------------------------------------------------------------------- 1 | package yamldiff 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | "github.com/goccy/go-yaml" 8 | ) 9 | 10 | type DiffStatus int 11 | 12 | const ( 13 | DiffStatusSame DiffStatus = 1 14 | DiffStatusDiff DiffStatus = 2 15 | DiffStatus1Missing DiffStatus = 3 16 | DiffStatus2Missing DiffStatus = 4 17 | 18 | fakeForMissingKey = "000_unexpected-key_000" 19 | ) 20 | 21 | type ( 22 | rawType = interface{} 23 | rawTypeMap = yaml.MapSlice 24 | rawTypeArray = []rawType 25 | 26 | _missingKey struct{} 27 | 28 | diff struct { 29 | a rawType 30 | b rawType 31 | children *diffChildren 32 | 33 | status DiffStatus 34 | diffCount int 35 | treeLevel int 36 | } 37 | 38 | diffChildrenArray = []*diff 39 | diffChildrenMap = map[string]*diff 40 | 41 | diffChildren struct { 42 | a diffChildrenArray 43 | m diffChildrenMap 44 | } 45 | ) 46 | 47 | //nolint:gochecknoglobals 48 | var missingKey = _missingKey{} 49 | 50 | func (r *runner) performDiff(rawA rawType, rawB rawType, level int) *diff { 51 | if rawA == nil || rawB == nil || rawA == missingKey || rawB == missingKey { 52 | return r.handlePrimitive(rawA, rawB, level) 53 | } 54 | 55 | if res := r.handleMap(rawA, rawB, level); res != nil { 56 | return res 57 | } 58 | 59 | if res := r.handleArray(rawA, rawB, level); res != nil { 60 | return res 61 | } 62 | 63 | // other case -> handle as primitive (int/float/bool/string) 64 | return r.handlePrimitive(rawA, rawB, level) 65 | } 66 | 67 | func (r *runner) handleMap(rawA rawType, rawB rawType, level int) *diff { 68 | result := &diff{ 69 | a: rawA, 70 | b: rawB, 71 | treeLevel: level, 72 | } 73 | 74 | mapA, mapAok := tryMap(rawA) 75 | mapB, mapBok := tryMap(rawB) 76 | 77 | // if both are not map 78 | if !mapAok && !mapBok { 79 | return nil 80 | } 81 | 82 | // if A is not map but B is map -> it's different data 83 | if !mapAok || !mapBok { 84 | result.status = DiffStatusDiff 85 | result.diffCount = r.handlePrimitive(rawA, rawB, level).diffCount 86 | 87 | return result 88 | } 89 | 90 | // if both are map 91 | 92 | result.children = &diffChildren{ 93 | m: diffChildrenMap{}, 94 | } 95 | result.status = DiffStatusSame 96 | 97 | // if B is map -> check the same key children 98 | for _, valA := range mapA { 99 | keyA, ok := valA.Key.(string) 100 | if !ok { 101 | keyA = fakeForMissingKey 102 | } 103 | 104 | foundKey := false 105 | for _, valB := range mapB { 106 | keyB, ok := valB.Key.(string) 107 | if !ok { 108 | keyB = fakeForMissingKey 109 | } 110 | 111 | if keyA != keyB { 112 | continue 113 | } 114 | 115 | result.children.m[keyA] = r.performDiff(valA.Value, valB.Value, level+1) 116 | if result.children.m[keyA].status != DiffStatusSame { 117 | result.status = DiffStatusDiff // top level diff can't specify actual reason 118 | } 119 | 120 | foundKey = true 121 | 122 | break 123 | } 124 | 125 | if !foundKey { 126 | result.children.m[keyA] = r.performDiff(valA.Value, missingKey, level+1) 127 | if result.children.m[keyA].status != DiffStatusSame { 128 | result.status = DiffStatusDiff // top level diff can't specify actual reason 129 | } 130 | } 131 | } 132 | 133 | // finding missing keyA 134 | for _, valB := range mapB { 135 | keyB, ok := valB.Key.(string) 136 | if !ok { 137 | keyB = fakeForMissingKey 138 | } 139 | 140 | foundKey := false 141 | for _, valA := range mapA { 142 | keyA, ok := valA.Key.(string) 143 | if !ok { 144 | keyA = fakeForMissingKey 145 | } 146 | 147 | if keyB != keyA { 148 | continue 149 | } 150 | 151 | foundKey = true 152 | 153 | break 154 | } 155 | 156 | if !foundKey { 157 | result.children.m[keyB] = r.performDiff(missingKey, valB.Value, level+1) 158 | if result.children.m[keyB].status != DiffStatusSame { 159 | result.status = DiffStatusDiff // top level diff can't specify actual reason 160 | } 161 | } 162 | } 163 | 164 | sum := 0 165 | for _, v := range result.children.m { 166 | sum += v.diffCount 167 | } 168 | result.diffCount = sum 169 | 170 | return result 171 | } 172 | 173 | func (r *runner) handleArray(rawA rawType, rawB rawType, level int) *diff { 174 | result := &diff{ 175 | a: rawA, 176 | b: rawB, 177 | treeLevel: level, 178 | } 179 | 180 | arrayA, arrayAok := tryArray(rawA) 181 | arrayB, arrayBok := tryArray(rawB) 182 | 183 | // if both are not array 184 | if !arrayAok && !arrayBok { 185 | return nil 186 | } 187 | 188 | // if A is not array but B is array -> it's different data 189 | if !arrayAok || !arrayBok { 190 | result.status = DiffStatusDiff 191 | result.diffCount = r.handlePrimitive(rawA, rawB, level).diffCount 192 | 193 | return result 194 | } 195 | 196 | // if both are array 197 | 198 | result.children = &diffChildren{ 199 | a: diffChildrenArray{}, 200 | } 201 | result.status = DiffStatusSame 202 | 203 | // check each elements is same or not 204 | diffs := map[string]*diff{} 205 | foundA := map[int]struct{}{} 206 | foundB := map[int]struct{}{} 207 | 208 | for keyA, valA := range arrayA { 209 | for keyB, valB := range arrayB { 210 | key := fmt.Sprintf("%d-%d", keyA, keyB) 211 | 212 | diffs[key] = r.performDiff(valA, valB, level+1) 213 | if diffs[key].status == DiffStatusSame { 214 | // store result and mark as confirmed 215 | result.children.a = append(result.children.a, diffs[key]) 216 | foundA[keyA] = struct{}{} 217 | foundB[keyB] = struct{}{} 218 | 219 | break 220 | } 221 | } 222 | } 223 | 224 | // found all elements, it's same array 225 | if len(foundA) == len(arrayA) && len(foundB) == len(arrayB) { 226 | return result 227 | } 228 | 229 | result.status = DiffStatusDiff 230 | 231 | // check diff elements 232 | for { 233 | // all confirmed arrayA, need to consider arrayB 234 | if len(foundA) == len(arrayA) { 235 | for k, v := range arrayB { 236 | if _, ok := foundB[k]; ok { 237 | continue 238 | } 239 | 240 | result.children.a = append(result.children.a, r.performDiff(nil, v, level+1)) 241 | } 242 | 243 | break 244 | } 245 | 246 | // all confirmed arrayB, need to consider in arrayA 247 | if len(foundB) == len(arrayB) { 248 | for k, v := range arrayA { 249 | if _, ok := foundA[k]; ok { 250 | continue 251 | } 252 | 253 | result.children.a = append(result.children.a, r.performDiff(v, nil, level+1)) 254 | } 255 | 256 | break 257 | } 258 | 259 | smallestDiff := &diff{diffCount: 100000} // FIXME 260 | smallestKeyA := 0 261 | smallestKeyB := 0 262 | 263 | for keyA := range arrayA { 264 | if _, ok := foundA[keyA]; ok { 265 | continue 266 | } 267 | 268 | for keyB := range arrayB { 269 | if _, ok := foundB[keyB]; ok { 270 | continue 271 | } 272 | 273 | key := fmt.Sprintf("%d-%d", keyA, keyB) 274 | if diffs[key].status == DiffStatusSame { 275 | continue // unexpected case 276 | } 277 | 278 | if smallestDiff.diffCount > diffs[key].diffCount { 279 | smallestDiff = diffs[key] 280 | smallestKeyA = keyA 281 | smallestKeyB = keyB 282 | } 283 | } 284 | } 285 | 286 | result.children.a = append(result.children.a, smallestDiff) 287 | foundA[smallestKeyA] = struct{}{} 288 | foundB[smallestKeyB] = struct{}{} 289 | } 290 | 291 | sum := 0 292 | for _, v := range result.children.a { 293 | sum += v.diffCount 294 | } 295 | result.diffCount = sum 296 | 297 | return result 298 | } 299 | 300 | func (r *runner) handlePrimitive(rawA rawType, rawB rawType, level int) *diff { 301 | result := &diff{ 302 | a: rawA, 303 | b: rawB, 304 | treeLevel: level, 305 | } 306 | 307 | strA := []rune(fmt.Sprint(rawA)) 308 | strB := []rune(fmt.Sprint(rawB)) 309 | 310 | switch { 311 | case rawA == nil && rawB == nil: 312 | result.status = DiffStatusSame 313 | case rawA == missingKey: 314 | switch { 315 | case r.option.emptyAsNull && (rawB == nil || string(strB) == "{}" || string(strB) == "[]"), 316 | r.option.zeroAsNull && (reflect.ValueOf(rawB).IsValid() && reflect.ValueOf(rawB).IsZero()): 317 | result.status = DiffStatusSame 318 | default: 319 | result.a = nil 320 | result.status = DiffStatus1Missing 321 | result.diffCount = len(strB) 322 | } 323 | 324 | case rawB == missingKey: 325 | switch { 326 | case r.option.emptyAsNull && rawA == nil, 327 | r.option.zeroAsNull && (reflect.ValueOf(rawA).IsValid() && reflect.ValueOf(rawA).IsZero()): 328 | result.status = DiffStatusSame 329 | default: 330 | result.b = nil 331 | result.status = DiffStatus2Missing 332 | result.diffCount = len(strA) 333 | } 334 | 335 | case rawA == nil: 336 | result.status = DiffStatusDiff 337 | result.diffCount = len(strB) 338 | case rawB == nil: 339 | result.status = DiffStatusDiff 340 | result.diffCount = len(strA) 341 | case rawA == rawB: 342 | result.status = DiffStatusSame 343 | default: 344 | result.status = DiffStatusDiff 345 | } 346 | 347 | // calculate diff size for diff 348 | if result.status == DiffStatusDiff { 349 | maxLen := len(strA) 350 | if lenB := len(strB); maxLen < lenB { 351 | maxLen = lenB 352 | } 353 | 354 | for nA, a := range strA { 355 | // lenA > lenB 356 | if len(strB) <= nA { 357 | result.diffCount = maxLen - nA 358 | 359 | break 360 | } 361 | 362 | // found diff in A and B strings 363 | if b := strB[nA]; a != b { 364 | result.diffCount = maxLen - nA 365 | 366 | break 367 | } 368 | } 369 | 370 | // guess lenA < lemB 371 | if result.diffCount == 0 { 372 | result.diffCount = maxLen - len(strA) 373 | } 374 | } 375 | 376 | return result 377 | } 378 | 379 | func tryMap(x rawType) (rawTypeMap, bool) { 380 | m, ok := x.(yaml.MapSlice) 381 | 382 | return m, ok 383 | } 384 | 385 | func tryMapItem(x rawType) (yaml.MapItem, bool) { 386 | m, ok := x.(yaml.MapItem) 387 | 388 | return m, ok 389 | } 390 | 391 | func tryArray(x rawType) (rawTypeArray, bool) { 392 | a, ok := x.([]interface{}) 393 | 394 | return a, ok 395 | } 396 | -------------------------------------------------------------------------------- /yamldiff/diff_test.go: -------------------------------------------------------------------------------- 1 | package yamldiff 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/goccy/go-yaml" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func Test_performDiff(t *testing.T) { 11 | tests := map[string]map[string]struct { 12 | a rawType 13 | b rawType 14 | want *diff 15 | }{ 16 | "primitive": { 17 | "int ok": { 18 | a: 1, 19 | b: 1, 20 | want: &diff{ 21 | status: DiffStatusSame, 22 | }, 23 | }, 24 | "int diff": { 25 | a: 1, 26 | b: 0, 27 | want: &diff{ 28 | status: DiffStatusDiff, 29 | diffCount: 1, 30 | }, 31 | }, 32 | "int null a": { 33 | b: 1, 34 | want: &diff{ 35 | status: DiffStatusDiff, 36 | diffCount: 5, 37 | }, 38 | }, 39 | "int null b": { 40 | a: 11, 41 | want: &diff{ 42 | status: DiffStatusDiff, 43 | diffCount: 5, 44 | }, 45 | }, 46 | "string ok": { 47 | a: "1", 48 | b: "1", 49 | want: &diff{ 50 | status: DiffStatusSame, 51 | }, 52 | }, 53 | "string diff": { 54 | a: "1", 55 | b: "0", 56 | want: &diff{ 57 | status: DiffStatusDiff, 58 | diffCount: 1, 59 | }, 60 | }, 61 | "string null a": { 62 | b: "1", 63 | want: &diff{ 64 | status: DiffStatusDiff, 65 | diffCount: 5, 66 | }, 67 | }, 68 | "string null b": { 69 | a: "11", 70 | want: &diff{ 71 | status: DiffStatusDiff, 72 | diffCount: 5, 73 | }, 74 | }, 75 | "int vs string": { 76 | a: "1", 77 | b: 1, 78 | want: &diff{ 79 | status: DiffStatusDiff, 80 | diffCount: 0, // because it's only diff on type 81 | }, 82 | }, 83 | "int vs string 2": { 84 | a: "1", 85 | b: 0, 86 | want: &diff{ 87 | status: DiffStatusDiff, 88 | diffCount: 1, 89 | }, 90 | }, 91 | "int vs float": { 92 | a: 1, 93 | b: 0.5, 94 | want: &diff{ 95 | status: DiffStatusDiff, 96 | diffCount: 3, 97 | }, 98 | }, 99 | "float vs string": { 100 | a: "1", 101 | b: 0.5, 102 | want: &diff{ 103 | status: DiffStatusDiff, 104 | diffCount: 3, 105 | }, 106 | }, 107 | "int vs bool": { 108 | a: 1, 109 | b: false, 110 | want: &diff{ 111 | status: DiffStatusDiff, 112 | diffCount: 5, 113 | }, 114 | }, 115 | }, 116 | "array": { 117 | "simple same": { 118 | a: rawTypeArray{1, 2, 3}, 119 | b: rawTypeArray{1, 2, 3}, 120 | want: &diff{ 121 | children: &diffChildren{ 122 | a: diffChildrenArray{ 123 | {a: 1, b: 1, status: DiffStatusSame, treeLevel: 1}, 124 | {a: 2, b: 2, status: DiffStatusSame, treeLevel: 1}, 125 | {a: 3, b: 3, status: DiffStatusSame, treeLevel: 1}, 126 | }, 127 | }, 128 | status: DiffStatusSame, 129 | }, 130 | }, 131 | "simple same different order": { 132 | a: rawTypeArray{1, 2, 3}, 133 | b: rawTypeArray{3, 1, 2}, 134 | want: &diff{ 135 | children: &diffChildren{ 136 | a: diffChildrenArray{ 137 | {a: 1, b: 1, status: DiffStatusSame, treeLevel: 1}, 138 | {a: 2, b: 2, status: DiffStatusSame, treeLevel: 1}, 139 | {a: 3, b: 3, status: DiffStatusSame, treeLevel: 1}, 140 | }, 141 | }, 142 | status: DiffStatusSame, 143 | }, 144 | }, 145 | "missing in A": { 146 | a: rawTypeArray{1, 2}, 147 | b: rawTypeArray{1, 2, 3}, 148 | want: &diff{ 149 | children: &diffChildren{ 150 | a: diffChildrenArray{ 151 | {a: 1, b: 1, status: DiffStatusSame, treeLevel: 1}, 152 | {a: 2, b: 2, status: DiffStatusSame, treeLevel: 1}, 153 | {b: 3, status: DiffStatusDiff, diffCount: 5, treeLevel: 1}, 154 | }, 155 | }, 156 | diffCount: 5, 157 | status: DiffStatusDiff, 158 | }, 159 | }, 160 | "missing in B": { 161 | a: rawTypeArray{1, 2, 3}, 162 | b: rawTypeArray{1, 3}, 163 | want: &diff{ 164 | children: &diffChildren{ 165 | a: diffChildrenArray{ 166 | {a: 1, b: 1, status: DiffStatusSame, treeLevel: 1}, 167 | {a: 3, b: 3, status: DiffStatusSame, treeLevel: 1}, 168 | {a: 2, status: DiffStatusDiff, diffCount: 5, treeLevel: 1}, // missing is added by last 169 | }, 170 | }, 171 | diffCount: 5, 172 | status: DiffStatusDiff, 173 | }, 174 | }, 175 | "missing in A and B": { 176 | a: rawTypeArray{1, 2, 3}, 177 | b: rawTypeArray{1, 3, 4}, 178 | want: &diff{ 179 | children: &diffChildren{ 180 | a: diffChildrenArray{ 181 | {a: 1, b: 1, status: DiffStatusSame, treeLevel: 1}, 182 | {a: 3, b: 3, status: DiffStatusSame, treeLevel: 1}, 183 | {a: 2, b: 4, status: DiffStatusDiff, diffCount: 1, treeLevel: 1}, // because can't find missing, it's diff. 184 | }, 185 | }, 186 | diffCount: 1, 187 | status: DiffStatusDiff, 188 | }, 189 | }, 190 | "complicated": { 191 | a: rawTypeArray{1, rawTypeArray{2, 3, 4}, 5, 6}, 192 | b: rawTypeArray{1, 5, rawTypeArray{2}}, 193 | want: &diff{ 194 | children: &diffChildren{ 195 | a: diffChildrenArray{ 196 | {a: 1, b: 1, status: DiffStatusSame, treeLevel: 1}, 197 | {a: 5, b: 5, status: DiffStatusSame, treeLevel: 1}, 198 | { 199 | a: 6, 200 | b: rawTypeArray{2}, 201 | diffCount: 3, 202 | status: DiffStatusDiff, 203 | treeLevel: 1, 204 | }, 205 | { 206 | a: rawTypeArray{2, 3, 4}, 207 | status: DiffStatusDiff, 208 | diffCount: 7, 209 | treeLevel: 1, 210 | }, 211 | }, 212 | }, 213 | diffCount: 3 + 7, 214 | status: DiffStatusDiff, 215 | }, 216 | }, 217 | }, 218 | "map": { 219 | "simple same": { 220 | a: rawTypeMap{ 221 | yaml.MapItem{Key: "foo", Value: "bar"}, 222 | }, 223 | b: rawTypeMap{ 224 | yaml.MapItem{Key: "foo", Value: "bar"}, 225 | }, 226 | want: &diff{ 227 | children: &diffChildren{ 228 | m: diffChildrenMap{ 229 | "foo": { 230 | a: "bar", 231 | b: "bar", 232 | status: DiffStatusSame, 233 | treeLevel: 1, 234 | }, 235 | }, 236 | }, 237 | status: DiffStatusSame, 238 | }, 239 | }, 240 | "simple diff": { 241 | a: rawTypeMap{ 242 | yaml.MapItem{Key: "foo", Value: "bar"}, 243 | }, 244 | b: rawTypeMap{ 245 | yaml.MapItem{Key: "foo", Value: "baz"}, 246 | }, 247 | want: &diff{ 248 | children: &diffChildren{ 249 | m: diffChildrenMap{ 250 | "foo": { 251 | a: "bar", 252 | b: "baz", 253 | status: DiffStatusDiff, 254 | diffCount: 1, 255 | treeLevel: 1, 256 | }, 257 | }, 258 | }, 259 | diffCount: 1, 260 | status: DiffStatusDiff, 261 | }, 262 | }, 263 | "simple diff type": { 264 | a: rawTypeMap{ 265 | yaml.MapItem{Key: "foo", Value: "bar"}, 266 | }, 267 | b: rawTypeMap{ 268 | yaml.MapItem{Key: "foo", Value: 1}, 269 | }, 270 | want: &diff{ 271 | children: &diffChildren{ 272 | m: diffChildrenMap{ 273 | "foo": { 274 | a: "bar", 275 | b: 1, 276 | diffCount: 3, 277 | status: DiffStatusDiff, 278 | treeLevel: 1, 279 | }, 280 | }, 281 | }, 282 | diffCount: 3, 283 | status: DiffStatusDiff, 284 | }, 285 | }, 286 | "simple diff type map and primitive": { 287 | a: rawTypeMap{ 288 | yaml.MapItem{Key: "foo", Value: "bar"}, 289 | }, 290 | b: rawTypeMap{ 291 | yaml.MapItem{ 292 | Key: "foo", 293 | Value: yaml.MapItem{ 294 | Key: "bar", 295 | Value: "baz", 296 | }, 297 | }, 298 | }, 299 | want: &diff{ 300 | children: &diffChildren{ 301 | m: diffChildrenMap{ 302 | "foo": { 303 | a: "bar", 304 | b: yaml.MapItem{ 305 | Key: "bar", 306 | Value: "baz", 307 | }, 308 | diffCount: len("{bar baz}"), // as primitive diff 309 | status: DiffStatusDiff, 310 | treeLevel: 1, 311 | }, 312 | }, 313 | }, 314 | 315 | diffCount: len("{bar baz}"), // from child 316 | status: DiffStatusDiff, 317 | }, 318 | }, 319 | "complicated": { 320 | a: rawTypeMap{ 321 | yaml.MapItem{ 322 | Key: "foo", 323 | Value: rawTypeMap{ 324 | yaml.MapItem{Key: "bar", Value: "baz"}, 325 | yaml.MapItem{Key: "baz", Value: 1}, 326 | yaml.MapItem{Key: "barr", Value: false}, 327 | }, 328 | }, 329 | yaml.MapItem{Key: "bar", Value: 1}, 330 | yaml.MapItem{Key: "baz", Value: "1"}, 331 | yaml.MapItem{Key: "zoo", Value: 1}, 332 | }, 333 | b: rawTypeMap{ 334 | yaml.MapItem{ 335 | Key: "foo", 336 | Value: rawTypeMap{ 337 | yaml.MapItem{Key: "bar", Value: "baz"}, 338 | yaml.MapItem{Key: "baz", Value: rawTypeMap{ 339 | yaml.MapItem{Key: "a", Value: "b"}, 340 | }}, 341 | yaml.MapItem{Key: "bazz", Value: 1}, 342 | }, 343 | }, 344 | yaml.MapItem{Key: "bar", Value: "1"}, 345 | yaml.MapItem{Key: "baz", Value: 1}, 346 | yaml.MapItem{Key: "boo", Value: 1}, 347 | }, 348 | want: &diff{ 349 | children: &diffChildren{ 350 | m: diffChildrenMap{ 351 | "foo": { 352 | a: rawTypeMap{ 353 | yaml.MapItem{Key: "bar", Value: "baz"}, 354 | yaml.MapItem{Key: "baz", Value: 1}, 355 | yaml.MapItem{Key: "barr", Value: false}, 356 | }, 357 | b: rawTypeMap{ 358 | yaml.MapItem{Key: "bar", Value: "baz"}, 359 | yaml.MapItem{Key: "baz", Value: rawTypeMap{ 360 | yaml.MapItem{Key: "a", Value: "b"}, 361 | }}, 362 | yaml.MapItem{Key: "bazz", Value: 1}, 363 | }, 364 | children: &diffChildren{ 365 | m: diffChildrenMap{ 366 | "bar": { 367 | a: "baz", 368 | b: "baz", 369 | status: DiffStatusSame, 370 | treeLevel: 2, 371 | }, 372 | "baz": { 373 | a: 1, 374 | b: rawTypeMap{ 375 | yaml.MapItem{Key: "a", Value: "b"}, 376 | }, 377 | status: DiffStatusDiff, 378 | diffCount: len("[{a b}]"), 379 | treeLevel: 2, 380 | }, 381 | "barr": { 382 | a: false, 383 | status: DiffStatus2Missing, 384 | diffCount: 5, 385 | treeLevel: 2, 386 | }, 387 | "bazz": { 388 | b: 1, 389 | status: DiffStatus1Missing, 390 | diffCount: 1, 391 | treeLevel: 2, 392 | }, 393 | }, 394 | }, 395 | diffCount: (len("[{a b}]")) + (5) + (1), 396 | status: DiffStatusDiff, 397 | treeLevel: 1, 398 | }, 399 | "bar": { 400 | a: 1, 401 | b: "1", 402 | diffCount: 0, 403 | status: DiffStatusDiff, 404 | treeLevel: 1, 405 | }, 406 | "baz": { 407 | a: "1", 408 | b: 1, 409 | diffCount: 0, 410 | status: DiffStatusDiff, 411 | treeLevel: 1, 412 | }, 413 | "zoo": { 414 | a: 1, 415 | diffCount: 1, 416 | status: DiffStatus2Missing, 417 | treeLevel: 1, 418 | }, 419 | "boo": { 420 | b: 1, 421 | diffCount: 1, 422 | status: DiffStatus1Missing, 423 | treeLevel: 1, 424 | }, 425 | }, 426 | }, 427 | diffCount: ((len("[{a b}]")) + (5) + (1)) + (0) + (0) + (1) + (1), 428 | status: DiffStatusDiff, 429 | }, 430 | }, 431 | }, 432 | "#27": { 433 | "creationTimestamp: null": { 434 | a: rawTypeMap{ 435 | yaml.MapItem{Key: "metadata", Value: rawTypeMap{ 436 | yaml.MapItem{Key: "creationTimestamp", Value: nil}, 437 | yaml.MapItem{Key: "name", Value: "nginx"}, 438 | yaml.MapItem{Key: "namespace", Value: "default"}, 439 | }}, 440 | yaml.MapItem{Key: "status", Value: nil}, 441 | }, 442 | b: rawTypeMap{ 443 | yaml.MapItem{Key: "metadata", Value: rawTypeMap{ 444 | yaml.MapItem{Key: "name", Value: "nginx"}, 445 | yaml.MapItem{Key: "namespace", Value: "default"}, 446 | }}, 447 | }, 448 | want: &diff{ 449 | children: &diffChildren{ 450 | m: diffChildrenMap{ 451 | "metadata": { 452 | a: rawTypeMap{ 453 | yaml.MapItem{Key: "creationTimestamp", Value: nil}, 454 | yaml.MapItem{Key: "name", Value: "nginx"}, 455 | yaml.MapItem{Key: "namespace", Value: "default"}, 456 | }, 457 | b: rawTypeMap{ 458 | yaml.MapItem{Key: "name", Value: "nginx"}, 459 | yaml.MapItem{Key: "namespace", Value: "default"}, 460 | }, 461 | children: &diffChildren{ 462 | m: diffChildrenMap{ 463 | "creationTimestamp": &diff{ 464 | status: DiffStatus2Missing, 465 | a: nil, 466 | treeLevel: 2, 467 | diffCount: 5, 468 | }, 469 | "name": &diff{ 470 | status: DiffStatusSame, 471 | a: "nginx", 472 | b: "nginx", 473 | treeLevel: 2, 474 | }, 475 | "namespace": &diff{ 476 | status: DiffStatusSame, 477 | a: "default", 478 | b: "default", 479 | treeLevel: 2, 480 | }, 481 | }, 482 | }, 483 | diffCount: 5, 484 | status: DiffStatusDiff, 485 | treeLevel: 1, 486 | }, 487 | "status": &diff{ 488 | status: DiffStatus2Missing, 489 | a: nil, 490 | diffCount: 5, 491 | treeLevel: 1, 492 | }, 493 | }, 494 | }, 495 | diffCount: 5 + 5, 496 | status: DiffStatusDiff, 497 | }, 498 | }, 499 | }, 500 | "#30": { 501 | "zero string": { 502 | a: rawTypeMap{ 503 | yaml.MapItem{Key: "strA", Value: "foo"}, 504 | yaml.MapItem{Key: "strB", Value: ""}, 505 | yaml.MapItem{Key: "strC", Value: ""}, 506 | }, 507 | b: rawTypeMap{ 508 | yaml.MapItem{Key: "strA", Value: "foo"}, 509 | yaml.MapItem{Key: "strB", Value: ""}, 510 | }, 511 | want: &diff{ 512 | children: &diffChildren{ 513 | m: diffChildrenMap{ 514 | "strA": &diff{ 515 | status: DiffStatusSame, 516 | a: "foo", 517 | b: "foo", 518 | treeLevel: 1, 519 | }, 520 | "strB": &diff{ 521 | status: DiffStatusSame, 522 | a: "", 523 | b: "", 524 | treeLevel: 1, 525 | }, 526 | "strC": &diff{ 527 | status: DiffStatus2Missing, 528 | a: "", 529 | treeLevel: 1, 530 | }, 531 | }, 532 | }, 533 | status: DiffStatusDiff, 534 | }, 535 | }, 536 | "zero int": { 537 | a: rawTypeMap{ 538 | yaml.MapItem{Key: "intA", Value: 5}, 539 | yaml.MapItem{Key: "intB", Value: 0}, 540 | yaml.MapItem{Key: "intC", Value: 0}, 541 | }, 542 | b: rawTypeMap{ 543 | yaml.MapItem{Key: "intA", Value: 5}, 544 | yaml.MapItem{Key: "intB", Value: 0}, 545 | }, 546 | want: &diff{ 547 | children: &diffChildren{ 548 | m: diffChildrenMap{ 549 | "intA": &diff{ 550 | status: DiffStatusSame, 551 | a: 5, 552 | b: 5, 553 | treeLevel: 1, 554 | }, 555 | "intB": &diff{ 556 | status: DiffStatusSame, 557 | a: 0, 558 | b: 0, 559 | treeLevel: 1, 560 | }, 561 | "intC": &diff{ 562 | status: DiffStatus2Missing, 563 | a: 0, 564 | diffCount: 1, 565 | treeLevel: 1, 566 | }, 567 | }, 568 | }, 569 | diffCount: 1, 570 | status: DiffStatusDiff, 571 | }, 572 | }, 573 | }, 574 | } 575 | for n, tt := range tests { 576 | t.Run(n, func(t *testing.T) { 577 | // t.Parallel() 578 | 579 | for n, tc := range tt { 580 | t.Run(n, func(t *testing.T) { 581 | // t.Parallel() 582 | 583 | got := (&runner{}).performDiff(tc.a, tc.b, 0) 584 | 585 | tc.want.a = tc.a 586 | tc.want.b = tc.b 587 | assert.Equal(t, tc.want, got) 588 | }) 589 | } 590 | }) 591 | } 592 | } 593 | 594 | func Test_performDiff_emptyAsNull(t *testing.T) { 595 | tests := map[string]map[string]struct { 596 | a rawType 597 | b rawType 598 | want *diff 599 | }{ 600 | "#27": { 601 | "creationTimestamp: null": { 602 | a: rawTypeMap{ 603 | yaml.MapItem{Key: "metadata", Value: rawTypeMap{ 604 | yaml.MapItem{Key: "creationTimestamp", Value: nil}, 605 | yaml.MapItem{Key: "name", Value: "nginx"}, 606 | yaml.MapItem{Key: "namespace", Value: "default"}, 607 | }}, 608 | yaml.MapItem{Key: "status", Value: nil}, 609 | }, 610 | b: rawTypeMap{ 611 | yaml.MapItem{Key: "metadata", Value: rawTypeMap{ 612 | yaml.MapItem{Key: "name", Value: "nginx"}, 613 | yaml.MapItem{Key: "namespace", Value: "default"}, 614 | }}, 615 | }, 616 | want: &diff{ 617 | children: &diffChildren{ 618 | m: diffChildrenMap{ 619 | "metadata": { 620 | a: rawTypeMap{ 621 | yaml.MapItem{Key: "creationTimestamp", Value: nil}, 622 | yaml.MapItem{Key: "name", Value: "nginx"}, 623 | yaml.MapItem{Key: "namespace", Value: "default"}, 624 | }, 625 | b: rawTypeMap{ 626 | yaml.MapItem{Key: "name", Value: "nginx"}, 627 | yaml.MapItem{Key: "namespace", Value: "default"}, 628 | }, 629 | children: &diffChildren{ 630 | m: diffChildrenMap{ 631 | "creationTimestamp": &diff{ 632 | status: DiffStatusSame, 633 | a: nil, 634 | b: missingKey, 635 | treeLevel: 2, 636 | }, 637 | "name": &diff{ 638 | status: DiffStatusSame, 639 | a: "nginx", 640 | b: "nginx", 641 | treeLevel: 2, 642 | }, 643 | "namespace": &diff{ 644 | status: DiffStatusSame, 645 | a: "default", 646 | b: "default", 647 | treeLevel: 2, 648 | }, 649 | }, 650 | }, 651 | status: DiffStatusSame, 652 | treeLevel: 1, 653 | }, 654 | "status": &diff{ 655 | status: DiffStatusSame, 656 | a: nil, 657 | b: missingKey, 658 | treeLevel: 1, 659 | }, 660 | }, 661 | }, 662 | status: DiffStatusSame, 663 | }, 664 | }, 665 | }, 666 | } 667 | for n, tt := range tests { 668 | t.Run(n, func(t *testing.T) { 669 | // t.Parallel() 670 | 671 | for n, tc := range tt { 672 | t.Run(n, func(t *testing.T) { 673 | // t.Parallel() 674 | 675 | got := (&runner{option: doOptions{emptyAsNull: true}}).performDiff(tc.a, tc.b, 0) 676 | 677 | tc.want.a = tc.a 678 | tc.want.b = tc.b 679 | assert.Equal(t, tc.want, got) 680 | }) 681 | } 682 | }) 683 | } 684 | } 685 | 686 | func Test_performDiff_zeroAsNull(t *testing.T) { 687 | tests := map[string]map[string]struct { 688 | a rawType 689 | b rawType 690 | want *diff 691 | }{ 692 | "#30": { 693 | "zero string": { 694 | a: rawTypeMap{ 695 | yaml.MapItem{Key: "strA", Value: "foo"}, 696 | yaml.MapItem{Key: "strB", Value: ""}, 697 | yaml.MapItem{Key: "strC", Value: ""}, 698 | }, 699 | b: rawTypeMap{ 700 | yaml.MapItem{Key: "strA", Value: "foo"}, 701 | yaml.MapItem{Key: "strB", Value: ""}, 702 | }, 703 | want: &diff{ 704 | children: &diffChildren{ 705 | m: diffChildrenMap{ 706 | "strA": &diff{ 707 | status: DiffStatusSame, 708 | a: "foo", 709 | b: "foo", 710 | treeLevel: 1, 711 | }, 712 | "strB": &diff{ 713 | status: DiffStatusSame, 714 | a: "", 715 | b: "", 716 | treeLevel: 1, 717 | }, 718 | "strC": &diff{ 719 | status: DiffStatusSame, 720 | a: "", 721 | b: missingKey, 722 | treeLevel: 1, 723 | }, 724 | }, 725 | }, 726 | status: DiffStatusSame, 727 | }, 728 | }, 729 | "zero int": { 730 | a: rawTypeMap{ 731 | yaml.MapItem{Key: "intA", Value: 5}, 732 | yaml.MapItem{Key: "intB", Value: 0}, 733 | yaml.MapItem{Key: "intC", Value: 0}, 734 | }, 735 | b: rawTypeMap{ 736 | yaml.MapItem{Key: "intA", Value: 5}, 737 | yaml.MapItem{Key: "intB", Value: 0}, 738 | }, 739 | want: &diff{ 740 | children: &diffChildren{ 741 | m: diffChildrenMap{ 742 | "intA": &diff{ 743 | status: DiffStatusSame, 744 | a: 5, 745 | b: 5, 746 | treeLevel: 1, 747 | }, 748 | "intB": &diff{ 749 | status: DiffStatusSame, 750 | a: 0, 751 | b: 0, 752 | treeLevel: 1, 753 | }, 754 | "intC": &diff{ 755 | status: DiffStatusSame, 756 | a: 0, 757 | b: missingKey, 758 | treeLevel: 1, 759 | }, 760 | }, 761 | }, 762 | status: DiffStatusSame, 763 | }, 764 | }, 765 | }, 766 | } 767 | for n, tt := range tests { 768 | t.Run(n, func(t *testing.T) { 769 | // t.Parallel() 770 | 771 | for n, tc := range tt { 772 | t.Run(n, func(t *testing.T) { 773 | // t.Parallel() 774 | 775 | got := (&runner{option: doOptions{zeroAsNull: true}}).performDiff(tc.a, tc.b, 0) 776 | 777 | tc.want.a = tc.a 778 | tc.want.b = tc.b 779 | assert.Equal(t, tc.want, got) 780 | }) 781 | } 782 | }) 783 | } 784 | } 785 | -------------------------------------------------------------------------------- /yamldiff/printer.go: -------------------------------------------------------------------------------- 1 | package yamldiff 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "strings" 7 | ) 8 | 9 | const ( 10 | indentString = " " 11 | ) 12 | 13 | type sortedChildItem struct { 14 | k string 15 | v *diff 16 | } 17 | 18 | func indent(level int) string { 19 | return strings.Repeat(indentString, level) 20 | } 21 | 22 | func dumpData(b io.Writer, diffPrefix string, level int, v rawType) { 23 | if t, ok := tryMap(v); ok { 24 | dumpMap(b, diffPrefix, level, t) 25 | 26 | return 27 | } 28 | 29 | if t, ok := tryArray(v); ok { 30 | dumpArray(b, diffPrefix, level, t) 31 | 32 | return 33 | } 34 | 35 | dumpPrimitive(b, diffPrefix, level, "", v) 36 | } 37 | 38 | func dumpMap(b io.Writer, diffPrefix string, level int, m rawTypeMap) { 39 | for _, v := range m { 40 | k, ok := v.Key.(string) 41 | if !ok { 42 | k = "" 43 | } 44 | 45 | dumpMapItem(b, diffPrefix, level, k, v) 46 | } 47 | } 48 | 49 | func dumpArray(b io.Writer, diffPrefix string, level int, m rawTypeArray) { 50 | for _, v := range m { 51 | dumpArrayItem(b, diffPrefix, level, v) 52 | } 53 | } 54 | 55 | func dumpArrayItem(b io.Writer, diffPrefix string, level int, v rawType) { 56 | if t, ok := tryMap(v); ok { 57 | fmt.Fprintf(b, "%s %s-\n", diffPrefix, indent(level)) 58 | dumpData(b, diffPrefix, level+1, t) 59 | 60 | return 61 | } 62 | 63 | if t, ok := tryArray(v); ok { 64 | fmt.Fprintf(b, "%s %s-\n", diffPrefix, indent(level)) 65 | dumpData(b, diffPrefix, level+1, t) 66 | 67 | return 68 | } 69 | 70 | dumpPrimitive(b, diffPrefix, level, "- ", v) 71 | } 72 | 73 | func dumpMapItem(b io.Writer, diffPrefix string, level int, k string, v rawType) { 74 | if t, ok := tryMap(v); ok { 75 | fmt.Fprintf(b, "%s %s%s:\n", diffPrefix, indent(level), k) 76 | dumpData(b, diffPrefix, level+1, t) 77 | 78 | return 79 | } 80 | 81 | if t, ok := tryArray(v); ok { 82 | fmt.Fprintf(b, "%s %s%s:\n", diffPrefix, indent(level), k) 83 | dumpData(b, diffPrefix, level+1, t) 84 | 85 | return 86 | } 87 | 88 | if t, ok := tryMapItem(v); ok { 89 | dumpMapItem(b, diffPrefix, level, k, t.Value) 90 | 91 | return 92 | } 93 | 94 | if v == nil { 95 | dumpPrimitive(b, diffPrefix, level, fmt.Sprintf("%s:", k), v) 96 | 97 | return 98 | } 99 | 100 | dumpPrimitive(b, diffPrefix, level, fmt.Sprintf("%s: ", k), v) 101 | } 102 | 103 | func dumpPrimitive(b io.Writer, diffPrefix string, level int, somethingPrefix string, v rawType) { 104 | switch v.(type) { 105 | case nil, _missingKey: 106 | fmt.Fprintf(b, "%s %s%s\n", diffPrefix, indent(level), somethingPrefix) 107 | case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: 108 | fmt.Fprintf(b, "%s %s%s%d\n", diffPrefix, indent(level), somethingPrefix, v) 109 | case float32, float64: 110 | fmt.Fprintf(b, "%s %s%s%f\n", diffPrefix, indent(level), somethingPrefix, v) 111 | case string: 112 | // try escape special characters 113 | fmt.Fprintf(b, "%s %s%s%#v\n", diffPrefix, indent(level), somethingPrefix, v) 114 | default: 115 | fmt.Fprintf(b, "%s %s%s%#v\n", diffPrefix, indent(level), somethingPrefix, v) 116 | } 117 | } 118 | 119 | func (d *diff) dump(b io.Writer, level int) { 120 | if d.children != nil { 121 | d.dumpTryArray(b, level) 122 | d.dumpTryMap(b, level) 123 | 124 | return 125 | } 126 | 127 | switch d.status { 128 | case DiffStatusSame: 129 | dumpData(b, " ", level, d.a) 130 | case DiffStatusDiff: 131 | if d.a != nil { 132 | dumpData(b, "-", level, d.a) 133 | } 134 | if d.b != nil { 135 | dumpData(b, "+", level, d.b) 136 | } 137 | case DiffStatus1Missing: 138 | dumpData(b, "+", level, d.b) 139 | case DiffStatus2Missing: 140 | dumpData(b, "-", level, d.a) 141 | } 142 | } 143 | 144 | func (d *diff) dumpTryArray(b io.Writer, level int) { 145 | if d.children.a == nil { 146 | return 147 | } 148 | 149 | for _, v := range d.children.a { 150 | if v.children != nil && (v.children.a != nil || v.children.m != nil) { 151 | fmt.Fprintf(b, " %s-\n", indent(level)) 152 | v.dump(b, level+1) 153 | 154 | continue 155 | } 156 | 157 | switch v.status { 158 | case DiffStatusSame: 159 | dumpArrayItem(b, " ", level, v.a) 160 | case DiffStatusDiff: 161 | dumpArrayItem(b, "-", level, v.a) 162 | dumpArrayItem(b, "+", level, v.b) 163 | case DiffStatus1Missing: 164 | dumpArrayItem(b, "+", level, v.b) 165 | case DiffStatus2Missing: 166 | dumpArrayItem(b, "-", level, v.a) 167 | } 168 | } 169 | } 170 | 171 | func (d *diff) dumpTryMap(b io.Writer, level int) { 172 | if d.children.m == nil { 173 | return 174 | } 175 | 176 | sortedChildren := []*sortedChildItem{} 177 | checked := map[string]struct{}{} 178 | 179 | appendSorted := func(r interface{}) { 180 | m, ok := tryMap(r) 181 | if !ok { 182 | return 183 | } 184 | 185 | for _, r := range m { 186 | for k, v := range d.children.m { 187 | if _, ok := checked[k]; ok { 188 | continue 189 | } 190 | if r.Key != k { 191 | continue 192 | } 193 | 194 | sortedChildren = append(sortedChildren, &sortedChildItem{ 195 | k: k, 196 | v: v, 197 | }) 198 | checked[k] = struct{}{} 199 | } 200 | } 201 | } 202 | 203 | appendSorted(d.a) 204 | appendSorted(d.b) 205 | 206 | for k, v := range d.children.m { 207 | if _, ok := checked[k]; ok { 208 | continue 209 | } 210 | 211 | sortedChildren = append(sortedChildren, &sortedChildItem{ 212 | k: k, 213 | v: v, 214 | }) 215 | } 216 | 217 | for _, r := range sortedChildren { 218 | if r.v.children != nil && (r.v.children.a != nil || r.v.children.m != nil) { 219 | fmt.Fprintf(b, " %s%s:\n", indent(level), r.k) 220 | r.v.dump(b, level+1) 221 | 222 | continue 223 | } 224 | 225 | switch r.v.status { 226 | case DiffStatusSame: 227 | dumpMapItem(b, " ", level, r.k, r.v.a) 228 | case DiffStatusDiff: 229 | dumpMapItem(b, "-", level, r.k, r.v.a) 230 | dumpMapItem(b, "+", level, r.k, r.v.b) 231 | case DiffStatus1Missing: 232 | dumpMapItem(b, "+", level, r.k, r.v.b) 233 | case DiffStatus2Missing: 234 | dumpMapItem(b, "-", level, r.k, r.v.a) 235 | } 236 | } 237 | } 238 | 239 | func (d *diff) Dump() string { 240 | var b strings.Builder 241 | 242 | d.dump(&b, d.treeLevel) 243 | 244 | return b.String() 245 | } 246 | -------------------------------------------------------------------------------- /yamldiff/printer_test.go: -------------------------------------------------------------------------------- 1 | package yamldiff 2 | 3 | import ( 4 | "sort" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/goccy/go-yaml" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func Test_diff_Dump(t *testing.T) { 13 | tests := map[string]map[string]struct { 14 | d *diff 15 | want string 16 | }{ 17 | "primitive": { 18 | "simple": { 19 | d: &diff{ 20 | a: 1, 21 | b: 1, 22 | status: DiffStatusSame, 23 | }, 24 | want: " 1\n", 25 | }, 26 | "diff": { 27 | d: &diff{ 28 | a: 1, 29 | b: 2, 30 | status: DiffStatusDiff, 31 | }, 32 | want: "- 1\n+ 2\n", 33 | }, 34 | "missing A": { 35 | d: &diff{ 36 | b: 2, 37 | status: DiffStatus1Missing, 38 | }, 39 | want: "+ 2\n", 40 | }, 41 | "missing B": { 42 | d: &diff{ 43 | a: 1, 44 | status: DiffStatus2Missing, 45 | }, 46 | want: "- 1\n", 47 | }, 48 | "diff but string": { 49 | d: &diff{ 50 | a: "1", 51 | b: "2", 52 | status: DiffStatusDiff, 53 | }, 54 | want: "- \"1\"\n+ \"2\"\n", 55 | }, 56 | "diff but bool": { 57 | d: &diff{ 58 | a: false, 59 | b: true, 60 | status: DiffStatusDiff, 61 | }, 62 | want: "- false\n+ true\n", 63 | }, 64 | }, 65 | "map": { 66 | "simple": { 67 | d: &diff{ 68 | children: &diffChildren{ 69 | m: diffChildrenMap{ 70 | "foo": { 71 | a: "bar", 72 | b: "bar", 73 | status: DiffStatusSame, 74 | treeLevel: 1, 75 | }, 76 | }, 77 | }, 78 | status: DiffStatusSame, 79 | }, 80 | want: " foo: \"bar\"\n", 81 | }, 82 | "diff": { 83 | d: &diff{ 84 | children: &diffChildren{ 85 | m: diffChildrenMap{ 86 | "foo": { 87 | a: "bar", 88 | b: "baz", 89 | status: DiffStatusDiff, 90 | diffCount: 1, 91 | treeLevel: 1, 92 | }, 93 | }, 94 | }, 95 | status: DiffStatusDiff, 96 | }, 97 | want: "- foo: \"bar\"\n+ foo: \"baz\"\n", 98 | }, 99 | "missing A": { 100 | d: &diff{ 101 | children: &diffChildren{ 102 | m: diffChildrenMap{ 103 | "foo": { 104 | b: "baz", 105 | status: DiffStatus1Missing, 106 | diffCount: 3, 107 | treeLevel: 1, 108 | }, 109 | }, 110 | }, 111 | status: DiffStatusDiff, 112 | }, 113 | want: "+ foo: \"baz\"\n", 114 | }, 115 | "missing B": { 116 | d: &diff{ 117 | children: &diffChildren{ 118 | m: diffChildrenMap{ 119 | "foo": { 120 | a: "bar", 121 | status: DiffStatus2Missing, 122 | diffCount: 3, 123 | treeLevel: 1, 124 | }, 125 | }, 126 | }, 127 | status: DiffStatusDiff, 128 | }, 129 | want: "- foo: \"bar\"\n", 130 | }, 131 | "complicated": { 132 | d: &diff{ 133 | children: &diffChildren{ 134 | m: diffChildrenMap{ 135 | "foo": { 136 | a: rawTypeMap{ 137 | yaml.MapItem{Key: "bar", Value: "baz"}, 138 | yaml.MapItem{Key: "baz", Value: 1}, 139 | yaml.MapItem{Key: "barr", Value: false}, 140 | }, 141 | b: rawTypeMap{ 142 | yaml.MapItem{Key: "bar", Value: "baz"}, 143 | yaml.MapItem{Key: "baz", Value: rawTypeMap{ 144 | yaml.MapItem{Key: "a", Value: "b"}, 145 | }}, 146 | yaml.MapItem{Key: "bazz", Value: 1}, 147 | }, 148 | children: &diffChildren{ 149 | m: diffChildrenMap{ 150 | "bar": { 151 | a: "baz", 152 | b: "baz", 153 | status: DiffStatusSame, 154 | treeLevel: 2, 155 | }, 156 | "baz": { 157 | a: 1, 158 | b: rawTypeMap{ 159 | yaml.MapItem{Key: "a", Value: "b"}, 160 | }, 161 | status: DiffStatusDiff, 162 | diffCount: len("map[a:b]"), 163 | treeLevel: 2, 164 | }, 165 | "barr": { 166 | a: false, 167 | status: DiffStatus2Missing, 168 | diffCount: 5, 169 | treeLevel: 2, 170 | }, 171 | "bazz": { 172 | b: 1, 173 | status: DiffStatus1Missing, 174 | diffCount: 1, 175 | treeLevel: 2, 176 | }, 177 | }, 178 | }, 179 | diffCount: (len("[{a b}]")) + (5) + (1), 180 | status: DiffStatusDiff, 181 | treeLevel: 1, 182 | }, 183 | "bar": { 184 | a: 1, 185 | b: "1", 186 | diffCount: 0, 187 | status: DiffStatusDiff, 188 | treeLevel: 1, 189 | }, 190 | "baz": { 191 | a: "1", 192 | b: 1, 193 | diffCount: 0, 194 | status: DiffStatusDiff, 195 | treeLevel: 1, 196 | }, 197 | "zoo": { 198 | a: 1, 199 | diffCount: 1, 200 | status: DiffStatus2Missing, 201 | treeLevel: 1, 202 | }, 203 | "boo": { 204 | b: 1, 205 | diffCount: 1, 206 | status: DiffStatus1Missing, 207 | treeLevel: 1, 208 | }, 209 | }, 210 | }, 211 | diffCount: ((len("[{a b}]")) + (5) + (1)) + (0) + (0) + (1) + (1), 212 | status: DiffStatusDiff, 213 | }, 214 | want: ` 215 | foo: 216 | bar: "baz" 217 | - baz: 1 218 | + baz: 219 | + a: "b" 220 | - barr: false 221 | + bazz: 1 222 | - bar: 1 223 | + bar: "1" 224 | - baz: "1" 225 | + baz: 1 226 | - zoo: 1 227 | + boo: 1`, 228 | }, 229 | }, 230 | "array": { 231 | "simple": { 232 | d: &diff{ 233 | children: &diffChildren{ 234 | a: diffChildrenArray{ 235 | { 236 | a: "bar", 237 | b: "bar", 238 | status: DiffStatusSame, 239 | treeLevel: 1, 240 | }, 241 | }, 242 | }, 243 | status: DiffStatusSame, 244 | }, 245 | want: " - \"bar\"\n", 246 | }, 247 | "diff": { 248 | d: &diff{ 249 | children: &diffChildren{ 250 | a: diffChildrenArray{ 251 | { 252 | a: "bar", 253 | b: "baz", 254 | status: DiffStatusDiff, 255 | treeLevel: 1, 256 | }, 257 | }, 258 | }, 259 | status: DiffStatusDiff, 260 | }, 261 | want: "- - \"bar\"\n+ - \"baz\"\n", 262 | }, 263 | "missing A": { 264 | d: &diff{ 265 | children: &diffChildren{ 266 | a: diffChildrenArray{ 267 | { 268 | b: "baz", 269 | status: DiffStatus1Missing, 270 | treeLevel: 1, 271 | }, 272 | }, 273 | }, 274 | status: DiffStatusDiff, 275 | }, 276 | want: "+ - \"baz\"\n", 277 | }, 278 | "missing B": { 279 | d: &diff{ 280 | children: &diffChildren{ 281 | a: diffChildrenArray{ 282 | { 283 | a: "bar", 284 | status: DiffStatus2Missing, 285 | treeLevel: 1, 286 | }, 287 | }, 288 | }, 289 | status: DiffStatusDiff, 290 | }, 291 | want: "- - \"bar\"\n", 292 | }, 293 | "complicated": { 294 | d: &diff{ 295 | children: &diffChildren{ 296 | a: diffChildrenArray{ 297 | {a: 1, b: 1, status: DiffStatusSame, treeLevel: 1}, 298 | {a: 5, b: 5, status: DiffStatusSame, treeLevel: 1}, 299 | { 300 | a: rawTypeArray{2, 3, 4}, 301 | b: rawTypeArray{2}, 302 | children: &diffChildren{ 303 | a: diffChildrenArray{ 304 | {a: 2, b: 2, status: DiffStatusSame, treeLevel: 2}, 305 | {a: 3, status: DiffStatus2Missing, diffCount: 1, treeLevel: 2}, 306 | {a: 4, status: DiffStatus2Missing, diffCount: 1, treeLevel: 2}, 307 | }, 308 | }, 309 | diffCount: 2, 310 | status: DiffStatusDiff, 311 | treeLevel: 1, 312 | }, 313 | {a: 6, status: DiffStatus2Missing, diffCount: 1, treeLevel: 1}, 314 | }, 315 | }, 316 | diffCount: 2 + 1, 317 | status: DiffStatusDiff, 318 | }, 319 | want: ` 320 | - 1 321 | - 5 322 | - 323 | - 2 324 | - - 3 325 | - - 4 326 | - - 6`, 327 | }, 328 | }, 329 | } 330 | for n, tt := range tests { 331 | t.Run(n, func(t *testing.T) { 332 | // t.Parallel() 333 | 334 | for n, tc := range tt { 335 | t.Run(n, func(t *testing.T) { 336 | // t.Parallel() 337 | 338 | gotSorted := strings.Split(tc.d.Dump(), "\n") 339 | sort.SliceStable(gotSorted, func(i, j int) bool { return gotSorted[i] < gotSorted[j] }) 340 | 341 | wantSorted := strings.Split(tc.want, "\n") 342 | sort.SliceStable(wantSorted, func(i, j int) bool { return wantSorted[i] < wantSorted[j] }) 343 | 344 | assert.Equal(t, wantSorted, gotSorted) 345 | }) 346 | } 347 | }) 348 | } 349 | } 350 | -------------------------------------------------------------------------------- /yamldiff/yaml.go: -------------------------------------------------------------------------------- 1 | package yamldiff 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | "math" 7 | "math/big" 8 | "sort" 9 | "strings" 10 | "time" 11 | 12 | "github.com/goccy/go-yaml" 13 | ) 14 | 15 | type RawYaml struct { 16 | raw interface{} 17 | id string 18 | } 19 | 20 | type RawYamlList []*RawYaml 21 | 22 | type Diffs []*diff 23 | 24 | func newRawYaml(raw interface{}) *RawYaml { 25 | return &RawYaml{ 26 | raw: raw, 27 | id: fmt.Sprintf("%d-%d", time.Now().UnixNano(), randInt()), 28 | } 29 | } 30 | 31 | func randInt() int64 { 32 | n, _ := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) 33 | 34 | return n.Int64() 35 | } 36 | 37 | func Load(s string) (RawYamlList, error) { 38 | yamls := strings.Split(s, "\n---\n") 39 | 40 | results := make(RawYamlList, 0, len(yamls)) 41 | for _, y := range yamls { 42 | var out interface{} 43 | if err := yaml.UnmarshalWithOptions([]byte(y), &out, yaml.UseOrderedMap()); err != nil { 44 | return nil, fmt.Errorf("yamldiff: failed to unmarshal yaml: %w", err) 45 | } 46 | 47 | results = append( 48 | results, 49 | newRawYaml(out), 50 | ) 51 | } 52 | 53 | return results, nil 54 | } 55 | 56 | type YamlDiff struct { 57 | d *diff 58 | idA string 59 | idB string 60 | } 61 | 62 | func (y *YamlDiff) Status() DiffStatus { 63 | return y.d.status 64 | } 65 | 66 | func (y *YamlDiff) Dump() string { 67 | return y.d.Dump() 68 | } 69 | 70 | type doOptions struct { 71 | emptyAsNull bool 72 | zeroAsNull bool 73 | } 74 | 75 | type DoOptionFunc func(o *doOptions) 76 | 77 | func EmptyAsNull() DoOptionFunc { 78 | return func(o *doOptions) { 79 | o.emptyAsNull = true 80 | } 81 | } 82 | 83 | func ZeroAsNull() DoOptionFunc { 84 | return func(o *doOptions) { 85 | o.zeroAsNull = true 86 | } 87 | } 88 | 89 | func Do(rawA RawYamlList, rawB RawYamlList, options ...DoOptionFunc) []*YamlDiff { 90 | opts := &doOptions{} 91 | for _, o := range options { 92 | o(opts) 93 | } 94 | 95 | r := &runner{ 96 | option: *opts, 97 | rawA: rawA, 98 | rawB: rawB, 99 | } 100 | 101 | r.performAllDiff() 102 | r.findMinimumDiffs() 103 | r.sortResult() 104 | 105 | return r.diffs 106 | } 107 | 108 | type runner struct { 109 | option doOptions 110 | rawA RawYamlList 111 | rawB RawYamlList 112 | diffs []*YamlDiff 113 | } 114 | 115 | func (r *runner) performAllDiff() { 116 | diffs := make([]*YamlDiff, 0, len(r.rawA)*len(r.rawB)) 117 | for _, a := range r.rawA { 118 | for _, b := range r.rawB { 119 | diffs = append(diffs, &YamlDiff{ 120 | d: r.performDiff(a.raw, b.raw, 0), 121 | idA: a.id, 122 | idB: b.id, 123 | }) 124 | } 125 | } 126 | 127 | // Make more diffs `A:nil`` and `nil:B`` to find missing entry 128 | for _, a := range r.rawA { 129 | diffs = append(diffs, &YamlDiff{ 130 | d: r.performDiff(a.raw, nil, 0), 131 | idA: a.id, 132 | idB: fmt.Sprintf("empty-%d-%d", time.Now().UnixNano(), randInt()), 133 | }) 134 | } 135 | 136 | for _, b := range r.rawB { 137 | diffs = append(diffs, &YamlDiff{ 138 | d: r.performDiff(nil, b.raw, 0), 139 | idA: fmt.Sprintf("empty-%d-%d", time.Now().UnixNano(), randInt()), 140 | idB: b.id, 141 | }) 142 | } 143 | 144 | r.diffs = diffs 145 | } 146 | 147 | func (r *runner) findMinimumDiffs() { 148 | sort.Slice(r.diffs, func(i, j int) bool { 149 | if r.diffs[i].d.status == DiffStatusSame { 150 | return true 151 | } 152 | return r.diffs[i].d.diffCount < r.diffs[j].d.diffCount 153 | }) 154 | 155 | result := []*YamlDiff{} 156 | checked := map[string]interface{}{} 157 | 158 | for _, d := range r.diffs { 159 | if _, ok := checked[d.idA]; ok { 160 | continue 161 | } 162 | if _, ok := checked[d.idB]; ok { 163 | continue 164 | } 165 | 166 | result = append(result, d) 167 | 168 | checked[d.idA] = struct{}{} 169 | checked[d.idB] = struct{}{} 170 | } 171 | 172 | // Even if missing entries in A or B, it should be covered by A:nil or nil:B case. 173 | 174 | r.diffs = result 175 | } 176 | 177 | func (r *runner) sortResult() { 178 | result := []*YamlDiff{} 179 | checked := map[string]interface{}{} 180 | 181 | for _, b := range r.rawA { 182 | for _, d := range r.diffs { 183 | if b.id != d.idA { 184 | continue 185 | } 186 | if _, ok := checked[d.idA]; ok { 187 | continue 188 | } 189 | if _, ok := checked[d.idB]; ok { 190 | continue 191 | } 192 | 193 | result = append(result, d) 194 | checked[d.idA] = struct{}{} 195 | checked[d.idB] = struct{}{} 196 | } 197 | } 198 | 199 | for _, b := range r.rawB { 200 | for _, d := range r.diffs { 201 | if b.id != d.idB { 202 | continue 203 | } 204 | if _, ok := checked[d.idA]; ok { 205 | continue 206 | } 207 | if _, ok := checked[d.idB]; ok { 208 | continue 209 | } 210 | 211 | result = append(result, d) 212 | checked[d.idA] = struct{}{} 213 | checked[d.idB] = struct{}{} 214 | } 215 | } 216 | 217 | r.diffs = result 218 | } 219 | -------------------------------------------------------------------------------- /yamldiff/yaml_test.go: -------------------------------------------------------------------------------- 1 | package yamldiff 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func confirmYaml(t *testing.T, yamlA, yamlB RawYamlList, want string, opts []DoOptionFunc) { 13 | t.Helper() 14 | 15 | result := "\n" 16 | for _, diff := range Do(yamlA, yamlB, opts...) { 17 | result += diff.Dump() 18 | result += "\n" 19 | } 20 | 21 | assert.Equal(t, strings.TrimSpace(want), strings.TrimSpace(result)) 22 | } 23 | 24 | func Test(t *testing.T) { 25 | yamlA := ` 26 | apiVersion: v1 27 | kind: Service 28 | metadata: 29 | name: my-service 30 | spec: 31 | selector: 32 | app: MyApp 33 | ports: 34 | - protocol: TCP 35 | port: 80 36 | targetPort: 9376 37 | --- 38 | apiVersion: apps/v1 39 | kind: Deployment 40 | metadata: 41 | name: app-deployment 42 | labels: 43 | app: MyApp 44 | spec: 45 | replicas: 3 46 | selector: 47 | matchLabels: 48 | app: MyApp 49 | template: 50 | metadata: 51 | labels: 52 | app: MyApp 53 | spec: 54 | containers: 55 | - name: app 56 | image: my-app:1.0.0 57 | ports: 58 | - containerPort: 9376 59 | --- 60 | foo: missing-in-b 61 | --- 62 | this: 63 | is: 64 | the: same 65 | empty: 66 | --- 67 | someStr: foo 68 | zeroStr: "" 69 | someInt: 5 70 | zeroInt: 0 71 | differs: fromA 72 | ` 73 | yamlB := ` 74 | metadata: 75 | name: my-service 76 | spec: 77 | ports: 78 | - protocol: TCP 79 | targetPort: 9376 80 | port: 8080 81 | selector: 82 | app: MyApp 83 | apiVersion: v1 84 | kind: Service 85 | --- 86 | apiVersion: apps/v1 87 | kind: Deployment 88 | spec: 89 | selector: 90 | matchLabels: 91 | app: MyApp 92 | replicas: 10 93 | template: 94 | metadata: 95 | labels: 96 | app: MyApp 97 | spec: 98 | containers: 99 | - name: app 100 | ports: 101 | - containerPort: 9376 102 | image: my-app:1.1.0 103 | metadata: 104 | name: app-deployment 105 | labels: 106 | app: MyApp 107 | --- 108 | bar: 109 | - missing in a.yaml 110 | --- 111 | baz: 112 | - missing in a.yaml 113 | --- 114 | this: 115 | is: 116 | the: same 117 | --- 118 | someStr: foo 119 | someInt: 5 120 | differs: fromB 121 | ` 122 | 123 | yamlsA, err := Load(yamlA) 124 | if err != nil { 125 | fmt.Fprintf(os.Stderr, "%+v", err) 126 | } 127 | 128 | yamlsB, err := Load(yamlB) 129 | if err != nil { 130 | fmt.Fprintf(os.Stderr, "%+v", err) 131 | } 132 | 133 | confirmYaml(t, yamlsA, yamlsB, resultOfNoOptions(), []DoOptionFunc{}) 134 | confirmYaml(t, yamlsA, yamlsB, resultOfWithEmpty(), []DoOptionFunc{EmptyAsNull()}) 135 | confirmYaml(t, yamlsA, yamlsB, resultOfWithZero(), []DoOptionFunc{ZeroAsNull()}) 136 | } 137 | 138 | func resultOfNoOptions() string { 139 | return ` 140 | apiVersion: "v1" 141 | kind: "Service" 142 | metadata: 143 | name: "my-service" 144 | spec: 145 | selector: 146 | app: "MyApp" 147 | ports: 148 | - 149 | protocol: "TCP" 150 | - port: 80 151 | + port: 8080 152 | targetPort: 9376 153 | 154 | apiVersion: "apps/v1" 155 | kind: "Deployment" 156 | metadata: 157 | name: "app-deployment" 158 | labels: 159 | app: "MyApp" 160 | spec: 161 | - replicas: 3 162 | + replicas: 10 163 | selector: 164 | matchLabels: 165 | app: "MyApp" 166 | template: 167 | metadata: 168 | labels: 169 | app: "MyApp" 170 | spec: 171 | containers: 172 | - 173 | name: "app" 174 | - image: "my-app:1.0.0" 175 | + image: "my-app:1.1.0" 176 | ports: 177 | - 178 | containerPort: 9376 179 | 180 | - foo: "missing-in-b" 181 | 182 | this: 183 | is: 184 | the: "same" 185 | - empty: 186 | 187 | someStr: "foo" 188 | - zeroStr: "" 189 | someInt: 5 190 | - zeroInt: 0 191 | - differs: "fromA" 192 | + differs: "fromB" 193 | 194 | + bar: 195 | + - "missing in a.yaml" 196 | 197 | + baz: 198 | + - "missing in a.yaml" 199 | 200 | ` 201 | } 202 | 203 | func resultOfWithEmpty() string { 204 | return ` 205 | apiVersion: "v1" 206 | kind: "Service" 207 | metadata: 208 | name: "my-service" 209 | spec: 210 | selector: 211 | app: "MyApp" 212 | ports: 213 | - 214 | protocol: "TCP" 215 | - port: 80 216 | + port: 8080 217 | targetPort: 9376 218 | 219 | apiVersion: "apps/v1" 220 | kind: "Deployment" 221 | metadata: 222 | name: "app-deployment" 223 | labels: 224 | app: "MyApp" 225 | spec: 226 | - replicas: 3 227 | + replicas: 10 228 | selector: 229 | matchLabels: 230 | app: "MyApp" 231 | template: 232 | metadata: 233 | labels: 234 | app: "MyApp" 235 | spec: 236 | containers: 237 | - 238 | name: "app" 239 | - image: "my-app:1.0.0" 240 | + image: "my-app:1.1.0" 241 | ports: 242 | - 243 | containerPort: 9376 244 | 245 | - foo: "missing-in-b" 246 | 247 | this: 248 | is: 249 | the: "same" 250 | empty: 251 | 252 | someStr: "foo" 253 | - zeroStr: "" 254 | someInt: 5 255 | - zeroInt: 0 256 | - differs: "fromA" 257 | + differs: "fromB" 258 | 259 | + bar: 260 | + - "missing in a.yaml" 261 | 262 | + baz: 263 | + - "missing in a.yaml" 264 | 265 | ` 266 | } 267 | 268 | func resultOfWithZero() string { 269 | return ` 270 | apiVersion: "v1" 271 | kind: "Service" 272 | metadata: 273 | name: "my-service" 274 | spec: 275 | selector: 276 | app: "MyApp" 277 | ports: 278 | - 279 | protocol: "TCP" 280 | - port: 80 281 | + port: 8080 282 | targetPort: 9376 283 | 284 | apiVersion: "apps/v1" 285 | kind: "Deployment" 286 | metadata: 287 | name: "app-deployment" 288 | labels: 289 | app: "MyApp" 290 | spec: 291 | - replicas: 3 292 | + replicas: 10 293 | selector: 294 | matchLabels: 295 | app: "MyApp" 296 | template: 297 | metadata: 298 | labels: 299 | app: "MyApp" 300 | spec: 301 | containers: 302 | - 303 | name: "app" 304 | - image: "my-app:1.0.0" 305 | + image: "my-app:1.1.0" 306 | ports: 307 | - 308 | containerPort: 9376 309 | 310 | - foo: "missing-in-b" 311 | 312 | this: 313 | is: 314 | the: "same" 315 | - empty: 316 | 317 | someStr: "foo" 318 | zeroStr: "" 319 | someInt: 5 320 | zeroInt: 0 321 | - differs: "fromA" 322 | + differs: "fromB" 323 | 324 | + bar: 325 | + - "missing in a.yaml" 326 | 327 | + baz: 328 | + - "missing in a.yaml" 329 | 330 | ` 331 | } 332 | 333 | func TestForSpecificIssues(t *testing.T) { 334 | tests := map[string]struct { 335 | yamlA string 336 | yamlB string 337 | option []DoOptionFunc 338 | want string 339 | }{ 340 | // TODO: It should be extracted as multiline format to understand easily. It needs to refactor (*diff).dump() 341 | "#52": { 342 | yamlA: ` 343 | data: 344 | config: | 345 | logging.a: false 346 | logging.b: false`, 347 | yamlB: ` 348 | data: 349 | config: | 350 | logging.a: false 351 | logging.c: false`, 352 | want: ` 353 | data: 354 | - config: "logging.a: false\nlogging.b: false" 355 | + config: "logging.a: false\nlogging.c: false"`, 356 | }, 357 | "#29": { 358 | yamlA: ` 359 | value: |- 360 | foo 361 | bar 362 | baz 363 | special 364 | multiline 365 | `, 366 | yamlB: ` 367 | value: "foo\nbar\nbaz\n\ 368 | special\n\ 369 | \ multiline" 370 | `, 371 | want: `value: "foo\nbar\nbaz\nspecial\n multiline"`, 372 | }, 373 | } 374 | 375 | for key, test := range tests { 376 | t.Run(key, func(t *testing.T) { 377 | yamlA, err := Load(test.yamlA) 378 | if err != nil { 379 | fmt.Fprintf(os.Stderr, "%+v", err) 380 | } 381 | 382 | yamlB, err := Load(test.yamlB) 383 | if err != nil { 384 | fmt.Fprintf(os.Stderr, "%+v", err) 385 | } 386 | 387 | confirmYaml(t, yamlA, yamlB, test.want, test.option) 388 | }) 389 | } 390 | } 391 | --------------------------------------------------------------------------------