validate/vendor: always tidy
**- What I did**
Prevent #44453 or similar by always running `go mod tidy` when checking vendoring.

**- How I did it**
Allow running individual steps in `hack/vendor.sh` while still using it as the exclusive wrapper for `go mod` by introducing 'subcommands'; the default behavior is identical to the previous (which is now aliased as the `all` subcommand).

Make `hack/validate/vendor` take advantage of these split steps, and refactor it to be more robust against whitespace/follow bash best practices.

**- How to verify it**
Manually; revert #44453 locally to test tidy detection, and commit a modification to a vendored file to test re-vendor detection.

**- Description for the changelog**
N/A

**- A picture of a cute animal (not mandatory but encouraged)**
![](https://cdn.discordapp.com/attachments/704333319697072231/1041724104077750373/78191E84-9FF7-4BE8-9F2D-D94EEEAA48FA.jpg)


hack/vendor.sh
#!/usr/bin/env bash

# This file is just wrapper around 'go mod vendor' tool.
# For updating dependencies you should change `vendor.mod` file in root of the
# project.

set -e
set -x

SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
"${SCRIPTDIR}"/go-mod-prepare.sh

GO111MODULE=auto go mod tidy -modfile 'vendor.mod' -compat 1.18
GO111MODULE=auto go mod vendor -modfile vendor.mod

#!/usr/bin/env bash
#
# This file is just a wrapper around the 'go mod vendor' tool.
# For updating dependencies you should change `vendor.mod` file in root of the
# project.

set -e

SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
"${SCRIPTDIR}"/go-mod-prepare.sh

export GO111MODULE=on

tidy() (
		set -x
		go mod tidy -modfile vendor.mod -compat 1.18
)

vendor() (
		set -x
		go mod vendor -modfile vendor.mod
)

help() {
	printf "%s:\n" "$(basename "$0")"
	echo "  - tidy: run go mod tidy"
	echo "  - vendor: run go mod vendor"
	echo "  - all: run tidy && vendor"
	echo "  - help: show this help"
}

case "$1" in
	tidy) tidy ;;
	vendor) vendor ;;
	""|all) tidy && vendor ;;
	*) help ;;
esac

I personally prefer to leave the uncommitted `go.mod` -- it lets me use VS Code or GoLand without having to maintain (and sync) a GOPATH. I think this is quite important to support as we want to make sure that contributors are using the source code from `vendor/` and not from a IDE-powered `go get` that is ignorant of modules.

This does lead to a disconnect where `GO111MODULE=off` is used on the command line, and `GO111MODULE=on` is used in the IDE to discover vendor code, but I think that it is fine as the usage in the IDE is just to discover external modules.

We can add this script to the functions if you want to avoid running it on `help`, however, my thoughts are that we should actually double down on it (that is to say, the uncommitted `go.mod` should **always** be present) and having this as a per-requisite mandatory step is fine.

That is because I think the [IDE setup docs](https://github.com/moby/moby/blob/master/docs/contributing/set-up-ide.md#configure-project-for-ide-optional) are deeply flawed and should instead prefer to use a Go Modules-based approach (so, running `./hack/go-mod-prepare.sh` would be a vital step in setting up an IDE) as using a GOPATH means you may have different versions of dependencies from the vendoring (in some IDEs, such as GoLand).