@@ -23,6 +23,8 @@ import (
23
23
"regexp"
24
24
"strconv"
25
25
"strings"
26
+
27
+ apimachineryversion "k8s.io/apimachinery/pkg/version"
26
28
)
27
29
28
30
// Version is an opaque representation of a version number
@@ -31,6 +33,7 @@ type Version struct {
31
33
semver bool
32
34
preRelease string
33
35
buildMetadata string
36
+ info apimachineryversion.Info
34
37
}
35
38
36
39
var (
@@ -145,6 +148,43 @@ func MustParseGeneric(str string) *Version {
145
148
return v
146
149
}
147
150
151
+ // Parse tries to do ParseSemantic first to keep more information.
152
+ // If ParseSemantic fails, it would just do ParseGeneric.
153
+ func Parse (str string ) (* Version , error ) {
154
+ v , err := parse (str , true )
155
+ if err != nil {
156
+ return parse (str , false )
157
+ }
158
+ return v , err
159
+ }
160
+
161
+ // MustParse is like Parse except that it panics on error
162
+ func MustParse (str string ) * Version {
163
+ v , err := Parse (str )
164
+ if err != nil {
165
+ panic (err )
166
+ }
167
+ return v
168
+ }
169
+
170
+ // ParseMajorMinor parses a "generic" version string and returns a version with the major and minor version.
171
+ func ParseMajorMinor (str string ) (* Version , error ) {
172
+ v , err := ParseGeneric (str )
173
+ if err != nil {
174
+ return nil , err
175
+ }
176
+ return MajorMinor (v .Major (), v .Minor ()), nil
177
+ }
178
+
179
+ // MustParseMajorMinor is like ParseMajorMinor except that it panics on error
180
+ func MustParseMajorMinor (str string ) * Version {
181
+ v , err := ParseMajorMinor (str )
182
+ if err != nil {
183
+ panic (err )
184
+ }
185
+ return v
186
+ }
187
+
148
188
// ParseSemantic parses a version string that exactly obeys the syntax and semantics of
149
189
// the "Semantic Versioning" specification (http://semver.org/) (although it ignores
150
190
// leading and trailing whitespace, and allows the version to be preceded by "v"). For
@@ -215,6 +255,32 @@ func (v *Version) WithMinor(minor uint) *Version {
215
255
return & result
216
256
}
217
257
258
+ // SubtractMinor returns the version with offset from the original minor, with the same major and no patch.
259
+ // If -offset >= current minor, the minor would be 0.
260
+ func (v * Version ) OffsetMinor (offset int ) * Version {
261
+ var minor uint
262
+ if offset >= 0 {
263
+ minor = v .Minor () + uint (offset )
264
+ } else {
265
+ diff := uint (- offset )
266
+ if diff < v .Minor () {
267
+ minor = v .Minor () - diff
268
+ }
269
+ }
270
+ return MajorMinor (v .Major (), minor )
271
+ }
272
+
273
+ // SubtractMinor returns the version diff minor versions back, with the same major and no patch.
274
+ // If diff >= current minor, the minor would be 0.
275
+ func (v * Version ) SubtractMinor (diff uint ) * Version {
276
+ return v .OffsetMinor (- int (diff ))
277
+ }
278
+
279
+ // AddMinor returns the version diff minor versions forward, with the same major and no patch.
280
+ func (v * Version ) AddMinor (diff uint ) * Version {
281
+ return v .OffsetMinor (int (diff ))
282
+ }
283
+
218
284
// WithPatch returns copy of the version object with requested patch number
219
285
func (v * Version ) WithPatch (patch uint ) * Version {
220
286
result := * v
@@ -224,6 +290,9 @@ func (v *Version) WithPatch(patch uint) *Version {
224
290
225
291
// WithPreRelease returns copy of the version object with requested prerelease
226
292
func (v * Version ) WithPreRelease (preRelease string ) * Version {
293
+ if len (preRelease ) == 0 {
294
+ return v
295
+ }
227
296
result := * v
228
297
result .components = []uint {v .Major (), v .Minor (), v .Patch ()}
229
298
result .preRelease = preRelease
@@ -345,6 +414,17 @@ func onlyZeros(array []uint) bool {
345
414
return true
346
415
}
347
416
417
+ // EqualTo tests if a version is equal to a given version.
418
+ func (v * Version ) EqualTo (other * Version ) bool {
419
+ if v == nil {
420
+ return other == nil
421
+ }
422
+ if other == nil {
423
+ return false
424
+ }
425
+ return v .compareInternal (other ) == 0
426
+ }
427
+
348
428
// AtLeast tests if a version is at least equal to a given minimum version. If both
349
429
// Versions are Semantic Versions, this will use the Semantic Version comparison
350
430
// algorithm. Otherwise, it will compare only the numeric components, with non-present
@@ -360,6 +440,11 @@ func (v *Version) LessThan(other *Version) bool {
360
440
return v .compareInternal (other ) == - 1
361
441
}
362
442
443
+ // GreaterThan tests if a version is greater than a given version.
444
+ func (v * Version ) GreaterThan (other * Version ) bool {
445
+ return v .compareInternal (other ) == 1
446
+ }
447
+
363
448
// Compare compares v against a version string (which will be parsed as either Semantic
364
449
// or non-Semantic depending on v). On success it returns -1 if v is less than other, 1 if
365
450
// it is greater than other, or 0 if they are equal.
@@ -370,3 +455,30 @@ func (v *Version) Compare(other string) (int, error) {
370
455
}
371
456
return v .compareInternal (ov ), nil
372
457
}
458
+
459
+ // WithInfo returns copy of the version object with requested info
460
+ func (v * Version ) WithInfo (info apimachineryversion.Info ) * Version {
461
+ result := * v
462
+ result .info = info
463
+ return & result
464
+ }
465
+
466
+ func (v * Version ) Info () * apimachineryversion.Info {
467
+ if v == nil {
468
+ return nil
469
+ }
470
+ // in case info is empty, or the major and minor in info is different from the actual major and minor
471
+ v .info .Major = itoa (v .Major ())
472
+ v .info .Minor = itoa (v .Minor ())
473
+ if v .info .GitVersion == "" {
474
+ v .info .GitVersion = v .String ()
475
+ }
476
+ return & v .info
477
+ }
478
+
479
+ func itoa (i uint ) string {
480
+ if i == 0 {
481
+ return ""
482
+ }
483
+ return strconv .Itoa (int (i ))
484
+ }
0 commit comments