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.
pull/221/head
Daniel Martí 3 years ago committed by GitHub
parent 1db6e1e230
commit c7ee0e08e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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

Loading…
Cancel
Save