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  }