gitee.com/gricks/utils@v1.0.8/version.go (about) 1 package utils 2 3 import ( 4 "fmt" 5 "regexp" 6 "sort" 7 "strconv" 8 ) 9 10 var ( 11 // https://semver.org 12 semverRegexp = regexp.MustCompile(`^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) 13 ) 14 15 type Version struct { 16 build string 17 prerelease string 18 segments []int64 19 original string 20 } 21 22 func NewVersion(v string) (*Version, error) { 23 matches := semverRegexp.FindStringSubmatch(v) 24 if matches == nil { 25 return nil, fmt.Errorf("invalid version: `%s`", v) 26 } 27 28 ver := &Version{} 29 for i := 1; i <= 3; i++ { 30 val, err := strconv.ParseInt(matches[i], 10, 64) 31 if err != nil { 32 return nil, fmt.Errorf("invalid version: `%s`, parse failed: `%v`", v, err) 33 } 34 ver.segments = append(ver.segments, val) 35 } 36 37 ver.prerelease = matches[4] 38 ver.build = matches[5] 39 ver.original = v 40 41 return ver, nil 42 } 43 44 func (v *Version) Compare(o *Version) int { 45 for i := 0; i < 3; i++ { 46 if v.segments[i] > o.segments[i] { 47 return 1 48 } else if v.segments[i] < o.segments[i] { 49 return -1 50 } 51 } 52 return 0 53 } 54 55 func (v *Version) Build() string { return v.build } 56 func (v *Version) PreRelease() string { return v.prerelease } 57 func (v *Version) Original() string { return v.original } 58 func (v *Version) String() string { return v.original } 59 60 // Sort 61 62 type Versions []*Version 63 64 func (v Versions) Len() int { return len(v) } 65 func (v Versions) Less(i, j int) bool { return v[i].Compare(v[j]) < 0 } 66 func (v Versions) Swap(i, j int) { v[i], v[j] = v[j], v[i] } 67 func (v Versions) Sort() { sort.Sort(v) }