@@ -5,82 +5,89 @@ import (
5
5
"fmt"
6
6
"os"
7
7
"runtime"
8
+ "runtime/debug"
8
9
"strings"
10
+ "sync"
9
11
)
10
12
11
13
var (
12
- name = "[NAME]"
13
- version = "[version unknown]"
14
- commit = "[commit unknown]"
15
- license = "[license unknown]"
16
- buildOptions = "[options unknown]"
17
- buildUser = "[user unknown]"
18
- buildHost = "[host unknown]"
19
- buildDate = "[date unknown]"
20
- buildSource = "[source unknown]"
21
-
22
- compareVersion bool
14
+ name string
15
+ version = "dev build"
16
+ buildSource = "[source unknown]"
17
+ license = "[license unknown]"
18
+
19
+ info * Info
20
+ loadInfo sync.Once
23
21
)
24
22
25
23
// Info holds the programs meta information.
26
24
type Info struct {
27
- Name string
28
- Version string
29
- License string
30
- Commit string
31
- BuildOptions string
32
- BuildUser string
33
- BuildHost string
34
- BuildDate string
35
- BuildSource string
25
+ Name string
26
+ Version string
27
+ License string
28
+ Commit string
29
+ Time string
30
+ Source string
31
+ Dirty bool
32
+
33
+ debug. BuildInfo
36
34
}
37
35
38
36
// Set sets meta information via the main routine. This should be the first thing your program calls.
39
37
func Set (setName string , setVersion string , setLicenseName string , compareVersionToTag bool ) {
40
38
name = setName
41
39
version = setVersion
42
40
license = setLicenseName
43
- compareVersion = compareVersionToTag
44
41
}
45
42
46
43
// GetInfo returns all the meta information about the program.
47
44
func GetInfo () * Info {
48
- return & Info {
49
- Name : name ,
50
- Version : version ,
51
- Commit : commit ,
52
- License : license ,
53
- BuildOptions : buildOptions ,
54
- BuildUser : buildUser ,
55
- BuildHost : buildHost ,
56
- BuildDate : buildDate ,
57
- BuildSource : buildSource ,
58
- }
45
+ loadInfo .Do (func () {
46
+ buildInfo , _ := debug .ReadBuildInfo ()
47
+ buildSettings := make (map [string ]string )
48
+ for _ , setting := range buildInfo .Settings {
49
+ buildSettings [setting .Key ] = setting .Value
50
+ }
51
+
52
+ info = & Info {
53
+ Name : name ,
54
+ Version : version ,
55
+ License : license ,
56
+ BuildInfo : * buildInfo ,
57
+ Source : buildSource ,
58
+ Commit : buildSettings ["vcs.revision" ],
59
+ Time : buildSettings ["vcs.time" ],
60
+ Dirty : buildSettings ["vcs.modified" ] == "true" ,
61
+ }
62
+ })
63
+
64
+ return info
59
65
}
60
66
61
67
// Version returns the short version string.
62
68
func Version () string {
63
- if ! compareVersion || strings .HasPrefix (commit , fmt .Sprintf ("tags/v%s-0-" , version )) {
64
- return version
69
+ info := GetInfo ()
70
+
71
+ if info .Dirty {
72
+ return version + "*"
65
73
}
66
- return version + "*"
74
+
75
+ return version
67
76
}
68
77
69
78
// FullVersion returns the full and detailed version string.
70
79
func FullVersion () string {
71
- s := ""
72
- if ! compareVersion || strings .HasPrefix (commit , fmt .Sprintf ("tags/v%s-0-" , version )) {
73
- s += fmt .Sprintf ("%s\n version %s\n " , name , version )
74
- } else {
75
- s += fmt .Sprintf ("%s\n development build, built on top version %s\n " , name , version )
76
- }
77
- s += fmt .Sprintf ("\n commit %s\n " , commit )
78
- s += fmt .Sprintf ("built with %s (%s) %s/%s\n " , runtime .Version (), runtime .Compiler , runtime .GOOS , runtime .GOARCH )
79
- s += fmt .Sprintf (" using options %s\n " , strings .ReplaceAll (buildOptions , "§" , " " ))
80
- s += fmt .Sprintf (" by %s@%s\n " , buildUser , buildHost )
81
- s += fmt .Sprintf (" on %s\n " , buildDate )
82
- s += fmt .Sprintf ("\n Licensed under the %s license.\n The source code is available here: %s" , license , buildSource )
83
- return s
80
+ info := GetInfo ()
81
+
82
+ builder := new (strings.Builder )
83
+
84
+ builder .WriteString (fmt .Sprintf ("%s\n version %s\n " , info .Name , Version ()))
85
+ builder .WriteString (fmt .Sprintf ("\n commit %s\n " , info .Commit ))
86
+ builder .WriteString (fmt .Sprintf ("built with %s (%s) %s/%s\n " , runtime .Version (), runtime .Compiler , runtime .GOOS , runtime .GOARCH ))
87
+ builder .WriteString (fmt .Sprintf (" on %s\n " , info .Time ))
88
+ builder .WriteString (fmt .Sprintf ("\n Licensed under the %s license.\n The source code is available here: %s" , license , info .Source ))
89
+
90
+ return builder .String ()
84
91
}
85
92
86
93
// CheckVersion checks if the metadata is ok.
@@ -92,17 +99,11 @@ func CheckVersion() error {
92
99
return nil // testing on windows
93
100
default :
94
101
// check version information
95
- if name == "[NAME]" {
102
+ if name == "[NAME]" || license == "[license unknown]" {
96
103
return errors .New ("must call SetInfo() before calling CheckVersion()" )
97
104
}
98
- if version == "[version unknown]" ||
99
- commit == "[commit unknown]" ||
100
- license == "[license unknown]" ||
101
- buildOptions == "[options unknown]" ||
102
- buildUser == "[user unknown]" ||
103
- buildHost == "[host unknown]" ||
104
- buildDate == "[date unknown]" ||
105
- buildSource == "[source unknown]" {
105
+
106
+ if version == "[version unknown]" {
106
107
return errors .New ("please build using the supplied build script.\n $ ./build {main.go|...}" )
107
108
}
108
109
}
0 commit comments