/
tools_version.go
251 lines (209 loc) · 7.03 KB
/
tools_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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
package cmd
import (
"fmt"
"os"
hashivers "github.com/hashicorp/go-version"
"github.com/spf13/cobra"
)
var versionQuiet bool
// tvCmd are helpers to manipulate software versions
var tvCmd = &cobra.Command{
Use: "version",
Short: "Version helpers",
Long: `
DESCRIPTION
Various commands to manipulate, verify and compare software versions.
`,
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
var ivCmd = &cobra.Command{
Use: "isvalid",
Short: "Check if a given string represents a valid version",
Long: `
DESCRIPTION
Check the passed string to validate that it respects semantic versioning rules.
It returns an error if the string is not correctly formatted.
Under the hood, we try to parse the version string using the hashicorp/go-version library.
- If the passed version is *not* valid, the process exits with status 1.
- When it is valid, the process simply exits with status 0.
If the "quiet" mode is enabled, the command simply returns 1 (true) or 0 (false), depending
on the passed argument, without writing to error out.
EXAMPLES
A valid version:
` + os.Args[0] + ` version isvalid 2.0.6-dev.20191205
A *non* valid version:
` + os.Args[0] + ` version isvalid 2.a
`,
Run: func(cm *cobra.Command, args []string) {
if len(args) != 1 {
cm.Printf("Please provide a version to parse\n")
os.Exit(1)
}
versionStr := args[0]
_, err := hashivers.NewVersion(versionStr)
if versionQuiet {
if err == nil {
cm.Println("1")
} else {
cm.Println("0")
}
os.Exit(0)
} else {
if err != nil {
cm.Printf("[%s] is *not* a valid version\n", versionStr)
os.Exit(1)
}
}
},
}
var irCmd = &cobra.Command{
Use: "isrelease",
Short: "Check if a given string represents a valid **RELEASE** version",
Long: `
DESCRIPTION
Check the passed string to validate that it respects semantic versioning rules
*and* represents a valid release version.
It returns an error if the string is not correctly formatted or represents a SNAPSHOT.
Under the hood, we try to parse the version string using the hashicorp/go-version library.
We then check that the passed string is not a pre-release, that is that is not suffixed
by "a hyphen and a series of dot separated identifiers immediately following the patch version",
see: https://semver.org
In case the passed version is *not* a valid release version, the process prints an error
and exits with status 1. Otherwise it simply exits silently with status 0.
If the "quiet" mode is enabled, the command simply returns 1 (true) or 0 (false), depending
on the passed argument, without writing to error out.
EXAMPLES
A valid release version:
` + os.Args[0] + ` version isrelease 2.0.6
A *non* release version:
` + os.Args[0] + ` version isrelease 2.0.6-dev.20191205
`,
Run: func(cm *cobra.Command, args []string) {
if len(args) != 1 {
cm.Printf("Please provide a single version to be parsed\n")
os.Exit(1)
}
versionStr := args[0]
resultOK := true
errMessage := ""
v, err := hashivers.NewVersion(versionStr)
if err != nil {
resultOK = false
errMessage = fmt.Sprintf("[%s] is *not* a valid version\n", versionStr)
}
if v.Prerelease() != "" {
resultOK = false
errMessage = fmt.Sprintf("[%s] is *not* a valid release version\n", versionStr)
}
if versionQuiet {
if resultOK {
cm.Println("1")
} else {
cm.Println("0")
}
os.Exit(0)
} else {
if !resultOK {
cm.Println(errMessage)
os.Exit(1)
}
// Valid release version and not quiet mode, nothing to do.
}
},
}
var igtCmd = &cobra.Command{
Use: "isgreater",
Short: "Compare the two versions, succeed when the first is greater than the second",
Long: `
DESCRIPTION
Check the passed strings to validate that they respects semantic versioning rules
and then compare them.
Under the hood, it tries to parse the version strings using the hashicorp/go-version library
and then compare the 2 resulting version structs.
The command prints an error and exits with status 1 if:
- one of the 2 strings is not a valid semantic version,
- the first version is not strictly greater than the second.
Otherwise, the command simply exits with status 0.
If the "quiet" mode is enabled, the command simply returns 1 (true) or 0 (false), depending
on the passed arguments, without writing to error out.
EXAMPLE
This exits with status 1:
` + os.Args[0] + ` version isgreater 2.0.6-dev.20191205 2.0.6
This returns 0 - false (and exits with status 0):
` + os.Args[0] + ` version isgreater --quiet 4.0.5-rc2 4.0.5
`,
Run: func(cm *cobra.Command, args []string) {
if len(args) != 2 {
cm.Printf("Please provide two versions to be compared\n")
os.Exit(1)
}
v1Str := args[0]
v2Str := args[1]
resultOK := true
errMessage := ""
v1, err := hashivers.NewVersion(v1Str)
if err != nil {
resultOK = false
errMessage = fmt.Sprintf("Passed version [%s] is not a valid version\n", v1Str)
}
v2, err := hashivers.NewVersion(v2Str)
if err != nil {
resultOK = false
errMessage = fmt.Sprintf("Passed version [%s] is not a valid version\n", v2Str)
}
if resultOK && !v1.GreaterThan(v2) {
resultOK = false
errMessage = fmt.Sprintf("Passed version [%s] is *not* greater than [%s]\n", v1Str, v2Str)
}
if versionQuiet {
if resultOK {
cm.Println("1")
} else {
cm.Println("0")
}
os.Exit(0)
} else {
if !resultOK {
cm.Println(errMessage)
os.Exit(1)
}
// Valid and ordered release versions, nothing to do.
}
},
}
// hiddenIvCmd is a hidden shortcut to keep an alias to the pre v4 existing command.
var hiddenIvCmd = &cobra.Command{
Use: "isvalid",
Hidden: true,
Short: "Check if a given string represents a valid version",
Run: func(cmd *cobra.Command, args []string) {
ivCmd.Run(cmd, args)
},
}
// hiddenIrCmd is a hidden shortcut to keep an alias to the pre v4 existing command.
var hiddenIrCmd = &cobra.Command{
Use: "isrelease",
Hidden: true,
Short: "Check if a given string represents a valid **RELEASE** version",
Run: func(cmd *cobra.Command, args []string) {
irCmd.Run(cmd, args)
},
}
// hiddenIgtCmd is a hidden shortcut to keep an alias to the pre v4 existing command.
var hiddenIgtCmd = &cobra.Command{
Use: "isgreater",
Hidden: true,
Short: "Compare the two versions, succeed when the first is greater than the second",
Run: func(cmd *cobra.Command, args []string) {
igtCmd.Run(cmd, args)
},
}
func init() {
ivCmd.Flags().BoolVarP(&versionQuiet, "quiet", "q", false, "Simply returns 1 (true) or 0 (false) if the version is valid or not, without writing to standard error stream")
irCmd.Flags().BoolVarP(&versionQuiet, "quiet", "q", false, "Simply returns 1 (true) or 0 (false) if the version represents valid release or not, without writing to standard error stream")
igtCmd.Flags().BoolVarP(&versionQuiet, "quiet", "q", false, "Simply returns 1 (true) or 0 (false) if first passed version is greater than the second, without writing to standard error stream")
tvCmd.AddCommand(ivCmd, irCmd, igtCmd)
ToolsCmd.AddCommand(tvCmd)
}