github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/fs/version/version.go (about) 1 package version 2 3 import ( 4 "fmt" 5 "regexp" 6 "strconv" 7 "strings" 8 9 "github.com/pkg/errors" 10 "github.com/rclone/rclone/fs" 11 ) 12 13 // Version represents a parsed rclone version number 14 type Version []int 15 16 var parseVersion = regexp.MustCompile(`^(?:rclone )?v(\d+)\.(\d+)(?:\.(\d+))?(?:-(\d+)(?:-(g[\wβ-]+))?)?$`) 17 18 // New parses a version number from a string 19 // 20 // This will be returned with up to 4 elements for major, minor, 21 // patch, subpatch release. 22 // 23 // If the version number represents a compiled from git version 24 // number, then it will be returned as major, minor, 999, 999 25 func New(in string) (v Version, err error) { 26 isGit := strings.HasSuffix(in, "-DEV") 27 if isGit { 28 in = in[:len(in)-4] 29 } 30 r := parseVersion.FindStringSubmatch(in) 31 if r == nil { 32 return v, errors.Errorf("failed to match version string %q", in) 33 } 34 atoi := func(s string) int { 35 i, err := strconv.Atoi(s) 36 if err != nil { 37 fs.Errorf(nil, "Failed to parse %q as int from %q: %v", s, in, err) 38 } 39 return i 40 } 41 v = Version{ 42 atoi(r[1]), // major 43 atoi(r[2]), // minor 44 } 45 if r[3] != "" { 46 v = append(v, atoi(r[3])) // patch 47 } else if r[4] != "" { 48 v = append(v, 0) // patch 49 } 50 if r[4] != "" { 51 v = append(v, atoi(r[4])) // dev 52 } 53 if isGit { 54 v = append(v, 999, 999) 55 } 56 return v, nil 57 } 58 59 // String converts v to a string 60 func (v Version) String() string { 61 var out []string 62 for _, vv := range v { 63 out = append(out, fmt.Sprint(vv)) 64 } 65 return strings.Join(out, ".") 66 } 67 68 // Cmp compares two versions returning >0, <0 or 0 69 func (v Version) Cmp(o Version) (d int) { 70 n := len(v) 71 if n > len(o) { 72 n = len(o) 73 } 74 for i := 0; i < n; i++ { 75 d = v[i] - o[i] 76 if d != 0 { 77 return d 78 } 79 } 80 return len(v) - len(o) 81 } 82 83 // IsGit returns true if the current version was compiled from git 84 func (v Version) IsGit() bool { 85 return len(v) >= 4 && v[2] == 999 && v[3] == 999 86 }