diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 56ffc35b..7c1a6792 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -72,7 +72,7 @@ jobs: steps: - name: Install Go env: - GO_COMMIT: e475cf2e705d4eda8647426e060898ab3f643610 # 2022-03-14 + GO_COMMIT: 80a7504a13a5dccb60757d1fc66d71bcba359799 # 2022-03-25 run: | cd $HOME mkdir $HOME/gotip diff --git a/main.go b/main.go index 2ca59b64..4b5ca3bf 100644 --- a/main.go +++ b/main.go @@ -42,11 +42,7 @@ import ( "mvdan.cc/garble/internal/literals" ) -var ( - flagSet = flag.NewFlagSet("garble", flag.ContinueOnError) - - version = "(devel)" // to match the default from runtime/debug -) +var flagSet = flag.NewFlagSet("garble", flag.ContinueOnError) var ( flagLiterals bool @@ -328,15 +324,47 @@ func mainErr(args []string) error { fmt.Fprintf(os.Stderr, "usage: garble version\n") return errJustExit(2) } - // 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 + info, ok := debug.ReadBuildInfo() + if !ok { + // The build binary was stripped of build info? + // Could be the case if garble built itself. + fmt.Println("unknown") + return nil + } + mod := &info.Main + if mod.Replace != nil { + mod = mod.Replace + } + + // For the tests. + if v := os.Getenv("GARBLE_TEST_VERSION"); v != "" { + mod.Version = v + } + if v := os.Getenv("GARBLE_TEST_SUM"); v != "" { + mod.Sum = v + } + if v := os.Getenv("GARBLE_TEST_SETTINGS"); v != "" { + var extra []debug.BuildSetting + if err := json.Unmarshal([]byte(v), &extra); err != nil { + return err + } + info.Settings = append(info.Settings, extra...) + } + + fmt.Printf("%s %s %s\n\n", mod.Path, mod.Version, mod.Sum) + fmt.Printf("Build settings:\n") + for _, setting := range info.Settings { + if setting.Value == "" { + continue // do empty build settings even matter? } - version = mod.Version + // The padding helps keep readability by aligning: + // + // veryverylong.key value + // short.key some-other-value + // + // Empirically, 16 is enough; the longest key seen is "vcs.revision". + fmt.Printf("%16s %s\n", setting.Key, setting.Value) } - fmt.Println(version) return nil case "reverse": return commandReverse(args) diff --git a/testdata/scripts/help.txt b/testdata/scripts/help.txt index c1039c71..884dcf24 100644 --- a/testdata/scripts/help.txt +++ b/testdata/scripts/help.txt @@ -77,8 +77,32 @@ stderr 'must precede command, like: garble -seed=random build \./pkg' [windows] ! garble C:\does\not\exist\compile stderr 'not running "garble \[command\]"' +# Test the version command. Note that test binaries exclude VCS build info, +# and we reuse the test binary for garble itself, so that's missing. +# To avoid building another garble binary, +# and to be able to use static VCS info, use an environment variable. +# First, test without the information, and then with it. +# +# Note that Go 1.18.0 shipped with -buildvcs=true for "go test", +# so it's a special case that we need to handle until 1.18.1 is out. garble version -stdout 'devel|^v0' +stdout -count=1 'mvdan.cc/garble \(devel\)' +stdout -count=1 'Build settings' +stdout -count=3 '-compiler|GOOS|GOARCH' +[go1.19] ! stdout 'vcs' + +env GARBLE_TEST_VERSION='v0.88.99' +env GARBLE_TEST_SUM='h1:someBase64epYSXwA' +# Obtained from a real build while developing. +env GARBLE_TEST_SETTINGS='[{"Key":"vcs","Value":"git"},{"Key":"vcs.revision","Value":"91ea246349544769f5100c29f79cb0f173abfeea"},{"Key":"vcs.time","Value":"2022-03-18T13:45:11Z"},{"Key":"vcs.modified","Value":"true"}]' +garble version +stdout -count=1 'mvdan.cc/garble v0\.88\.99 h1:someBase64epYSXwA' +stdout -count=1 'Build settings' +stdout -count=3 '-compiler|GOOS|GOARCH' +[go1.19] stdout -count=1 'vcs git' +[go1.19] stdout -count=1 'vcs.revision 91ea246349544769f5100c29f79cb0f173abfeea' +[go1.19] stdout -count=1 'vcs.time 2022-03-18T13:45:11Z' +[go1.19] stdout -count=1 'vcs.modified true' ! garble version -flag stderr 'usage: garble version'