1package main
2
3import (
4 "errors"
5 "fmt"
6 "runtime/debug"
7 "strings"
8
9 "github.com/git-bug/git-bug/commands"
10 "golang.org/x/mod/semver"
11)
12
13var (
14 version = "undefined"
15)
16
17// getVersion returns a string representing the version information defined when
18// the binary was built, or a sane default indicating a local build. a string is
19// always returned. an error may be returned along with the string in the event
20// that we detect a local build but are unable to get build metadata.
21//
22// TODO: support validation of the version (that it's a real version)
23// TODO: support notifying the user if their version is out of date
24func getVersion() (string, error) {
25 var arch string
26 var commit string
27 var modified bool
28 var platform string
29
30 var v strings.Builder
31
32 // this supports overriding the default version if the deprecated var used
33 // for setting the exact version for releases is supplied. we are doing this
34 // in order to give downstream package maintainers a longer window to
35 // migrate.
36 //
37 // TODO: 0.12.0: remove support for old build tags
38 if version == "undefined" && commands.GitExactTag != "" {
39 version = commands.GitExactTag
40 }
41
42 // automatically add the v prefix if it's missing
43 if version != "undefined" && !strings.HasPrefix(version, "v") {
44 version = fmt.Sprintf("v%s", version)
45 }
46
47 // reset the version string to undefined if it is invalid
48 if ok := semver.IsValid(version); !ok {
49 version = "undefined"
50 }
51
52 v.WriteString(version)
53
54 info, ok := debug.ReadBuildInfo()
55 if !ok {
56 v.WriteString(fmt.Sprintf(" (no build info)\n"))
57 return v.String(), errors.New("unable to read build metadata")
58 }
59
60 for _, kv := range info.Settings {
61 switch kv.Key {
62 case "GOOS":
63 platform = kv.Value
64 case "GOARCH":
65 arch = kv.Value
66 case "vcs.modified":
67 if kv.Value == "true" {
68 modified = true
69 }
70 case "vcs.revision":
71 commit = kv.Value
72 }
73 }
74
75 if commit != "" {
76 v.WriteString(fmt.Sprintf(" %.12s", commit))
77 }
78
79 if modified {
80 v.WriteString("/dirty")
81 }
82
83 v.WriteString(fmt.Sprintf(" %s", info.GoVersion))
84
85 if platform != "" {
86 v.WriteString(fmt.Sprintf(" %s", platform))
87 }
88
89 if arch != "" {
90 v.WriteString(fmt.Sprintf(" %s", arch))
91 }
92
93 return fmt.Sprint(v.String(), "\n"), nil
94}