/
version.go
105 lines (91 loc) · 2.72 KB
/
version.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) 2020, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information
package version
import (
"encoding/json"
"fmt"
"os"
"runtime"
"runtime/debug"
"time"
"golang.org/x/mod/module"
)
// Note that this is not a main package, so a "var version" will not work with
// our go-cross script which uses -ldflags=main.version=xxx.
const ourModulePath = "mvdan.cc/gofumpt"
const fallbackVersion = "(devel)" // to match the default from runtime/debug
func findModule(info *debug.BuildInfo, modulePath string) *debug.Module {
if info.Main.Path == modulePath {
return &info.Main
}
for _, dep := range info.Deps {
if dep.Path == modulePath {
return dep
}
}
return nil
}
func gofumptVersion() string {
info, ok := debug.ReadBuildInfo()
if !ok {
return fallbackVersion // no build info available
}
// Note that gofumpt may be used as a library via the format package,
// so we cannot assume it is the main module in the build.
mod := findModule(info, ourModulePath)
if mod == nil {
return fallbackVersion // not found?
}
if mod.Replace != nil {
mod = mod.Replace
}
// If we found a meaningful version, we are done.
// If gofumpt is not the main module, stop as well,
// as VCS info is only for the main module.
if mod.Version != "(devel)" || mod != &info.Main {
return mod.Version
}
// Fall back to trying to use VCS information.
// Until https://github.com/golang/go/issues/50603 is implemented,
// manually construct something like a pseudo-version.
// TODO: remove when this code is dead, hopefully in Go 1.20.
// For the tests, as we don't want the VCS information to change over time.
if v := os.Getenv("GARBLE_TEST_BUILDSETTINGS"); v != "" {
var extra []debug.BuildSetting
if err := json.Unmarshal([]byte(v), &extra); err != nil {
panic(err)
}
info.Settings = append(info.Settings, extra...)
}
var vcsTime time.Time
var vcsRevision string
for _, setting := range info.Settings {
switch setting.Key {
case "vcs.time":
// If the format is invalid, we'll print a zero timestamp.
vcsTime, _ = time.Parse(time.RFC3339Nano, setting.Value)
case "vcs.revision":
vcsRevision = setting.Value
if len(vcsRevision) > 12 {
vcsRevision = vcsRevision[:12]
}
}
}
if vcsRevision != "" {
return module.PseudoVersion("", "", vcsTime, vcsRevision)
}
return fallbackVersion
}
func goVersion() string {
// For the tests, as we don't want the Go version to change over time.
if testVersion := os.Getenv("GO_VERSION_TEST"); testVersion != "" {
return testVersion
}
return runtime.Version()
}
func String(injected string) string {
if injected != "" {
return fmt.Sprintf("%s (%s)", injected, goVersion())
}
return fmt.Sprintf("%s (%s)", gofumptVersion(), goVersion())
}