From c7ee0e08e52db87b85744b40757c0831035bc277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Wed, 3 Feb 2021 17:55:24 +0000 Subject: [PATCH] add a "version" command (#220) Mimicking "go version", this tells the user garble's own version. The code is exactly the same that is used for another tool written in Go, shfmt. It uses runtime/debug to fetch the module version embedded in binaries built by Go. For example: $ go get mvdan.cc/sh/v3/cmd/shfmt@latest $ shfmt -version v3.2.2 $ go get mvdan.cc/sh/v3/cmd/shfmt@master $ shfmt -version v3.3.0-0.dev.0.20210203135509-56c9918c980d Note that this will not work for a plain "go build" or "go install" after a "git clone", since in that case the Go tool can't know garble's own version via go.mod - since it's the current main module: $ go build $ ./garble version (devel) For the use case of the power user building from source directly, they are probably clever enough to tell us what git commit they are on, so this is not a big problem right now. It will also get better once golang/go#37475 is fixed in the future. Until then, if we need to do "release" builds locally, we can embed an explicit version into the binary via ldflags: $ go build -ldflags=-X=main.version=v1.2.3 $ ./garble version v1.2.3 Fixes #217. --- main.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 0084769..fb4dfd0 100644 --- a/main.go +++ b/main.go @@ -28,6 +28,7 @@ import ( "path/filepath" "reflect" "runtime" + "runtime/debug" "strings" "time" @@ -39,7 +40,11 @@ import ( "mvdan.cc/garble/internal/literals" ) -var flagSet = flag.NewFlagSet("garble", flag.ContinueOnError) +var ( + flagSet = flag.NewFlagSet("garble", flag.ContinueOnError) + + version = "(devel)" // to match the default from runtime/debug +) var ( flagGarbleLiterals bool @@ -245,6 +250,17 @@ func mainErr(args []string) error { switch cmd := args[0]; cmd { case "help": return flag.ErrHelp + case "version": + // don't overwrite the version if it was set by -ldflags=-X + if info, ok := debug.ReadBuildInfo(); ok && version == "(devel)" { + mod := &info.Main + if mod.Replace != nil { + mod = mod.Replace + } + version = mod.Version + } + fmt.Println(version) + return nil case "build", "test": if !goVersionOK() { return errJustExit