|
- package main
-
- import (
- "fmt"
- "strconv"
- "strings"
- )
-
- type Version struct {
- Major, Minor, Patch int
- }
-
- func (v Version) String() string {
- if v.Major < 0 {
- panic(fmt.Sprintf("cannot stringify invalid version (major is %d)", v.Major))
- }
- if v.Minor < 0 {
- return fmt.Sprintf("v%d", v.Major)
- }
- if v.Patch < 0 {
- return fmt.Sprintf("v%d.%d", v.Major, v.Minor)
- }
- return fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Patch)
- }
-
- func (v Version) Less(other Version) bool {
- if v.Major != other.Major {
- return v.Major < other.Major
- }
- if v.Minor != other.Minor {
- return v.Minor < other.Minor
- }
- return v.Patch < other.Patch
- }
-
- func (v Version) Contains(other Version) bool {
- if v.Patch != -1 {
- return v == other
- }
- if v.Minor != -1 {
- return v.Major == other.Major && v.Minor == other.Minor
- }
- return v.Major == other.Major
- }
-
- func (v Version) IsValid() bool {
- return v == InvalidVersion
- }
-
- var InvalidVersion = Version{-1, -1, -1}
- var TooHighVersion = Version{-2, -2, -2}
-
- func parseVersion(s string) (Version, bool) {
- if len(s) < 2 {
- return InvalidVersion, false
- }
- if s[0] != 'v' {
- return InvalidVersion, false
- }
- v := Version{-1, -1, -1}
-
- parts := strings.Split(s[1:], ".")
- if len(parts) == 0 || len(parts) > 3 {
- return InvalidVersion, false
- }
- for i, part := range parts {
- if len(part) == 0 || part[0] == '0' {
- return InvalidVersion, false
- }
- num, err := strconv.ParseInt(part, 10, 32)
- if err != nil {
- if err.(*strconv.NumError).Err == strconv.ErrRange {
- return TooHighVersion, false
- }
- return InvalidVersion, false
- }
- switch i {
- case 0:
- v.Major = int(num)
- case 1:
- v.Minor = int(num)
- case 2:
- v.Patch = int(num)
- }
- }
-
- return v, true
- }
|