gobin
gobin copied to clipboard
provide a way to set module-specific PATH
There are a couple usability issues related to absence of gobin-installed binaries in PATH.
First one is obvious: gobin -m -run github.com/golangci/golangci-lint/cmd/golangci-lint
is a way harder to type than just golangci-lint
.
Second is a bit more subtle: protoc
looks for installed plugins in PATH, so to let it find gobin-installed plugins we had to replace //go:generate protoc …
with something like //go:generate sh -c "protoc $(gobin -m -p $(go list -tags=tools -f '{{range .Imports}}{{println .}}{{end}}' ../../third_party | grep protoc-gen) | sed -e s,^,--plugin=,) …
(where ../../third-party
is a directory containing tools.go
).
Maybe it's worth to provide a way to run any command with PATH prepended with all directories with gobin-installed binaries in module-mode, e.g.:
# same as `export PATH=.gobincache/github.com/golangci/golangci-lint/@v/v1.31.0/cmd/golangci-lint:$PATH; golangci-lint`
$ gobin -m golangci-lint
# same as `export PATH=.gobincache/github.com/golangci/golangci-lint/@v/v1.31.0/cmd/golangci-lint:…other:installed:tools:here:…:$PATH; protoc …`
$ gobin -m protoc …
Of course we can set PATH right now using command shown below, but there are a couple issues with it:
- it's slow (probably related to #97) - running
/bin/true
this way took3.531 real 12.202 user 3.191 sys 43MB RAM
- it has to be re-run when tools/versions change
- there is no easy way to remove these dirs from PATH when switching to another project/directory
$ PATH=$(echo $(dirname $(gobin -m -p $(go list -tags=tools -f '{{range .Imports}}{{println .}}{{end}}' ./third_party))) | sed 's, ,:,g'):$PATH zsh
Here is tools.go used in examples above:
// +build tools
package third_party
import (
_ "github.com/cheekybits/genny"
_ "github.com/go-swagger/go-swagger/cmd/swagger"
_ "github.com/golang/mock/mockgen"
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
_ "github.com/googleapis/api-linter/cmd/api-linter"
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
_ "github.com/nilslice/protolock/cmd/protolock"
_ "github.com/yoheimuta/protolint/cmd/protoc-gen-protolint"
_ "github.com/yoheimuta/protolint/cmd/protolint"
_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
_ "gotest.tools/gotestsum"
)
First one is obvious:
gobin -m -run github.com/golangci/golangci-lint/cmd/golangci-lint
is a way harder to type than justgolangci-lint
.
Agreed. The generally accepted solution for humans is to use aliases. For scripts/go:generate
directives, it doesn't really matter.
Second is a bit more subtle:
protoc
looks for installed plugins in PATH,
I think this is just a case of a PATH
based tool running up against a non-PATH
based tool. In this case I would probably drop down to using a script.