github.com/gogf/gf/v2@v2.7.4/text/gstr/gstr_version.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gstr
     8  
     9  import (
    10  	"strings"
    11  
    12  	"github.com/gogf/gf/v2/util/gconv"
    13  )
    14  
    15  // IsGNUVersion checks and returns whether given `version` is valid GNU version string.
    16  func IsGNUVersion(version string) bool {
    17  	if version != "" && (version[0] == 'v' || version[0] == 'V') {
    18  		version = version[1:]
    19  	}
    20  	if version == "" {
    21  		return false
    22  	}
    23  	var array = strings.Split(version, ".")
    24  	if len(array) > 3 {
    25  		return false
    26  	}
    27  	for _, v := range array {
    28  		if v == "" {
    29  			return false
    30  		}
    31  		if !IsNumeric(v) {
    32  			return false
    33  		}
    34  		if v[0] == '-' || v[0] == '+' {
    35  			return false
    36  		}
    37  	}
    38  	return true
    39  }
    40  
    41  // CompareVersion compares `a` and `b` as standard GNU version.
    42  //
    43  // It returns  1 if `a` > `b`.
    44  //
    45  // It returns -1 if `a` < `b`.
    46  //
    47  // It returns  0 if `a` = `b`.
    48  //
    49  // GNU standard version is like:
    50  // v1.0
    51  // 1
    52  // 1.0.0
    53  // v1.0.1
    54  // v2.10.8
    55  // 10.2.0
    56  // etc.
    57  func CompareVersion(a, b string) int {
    58  	if a != "" && a[0] == 'v' {
    59  		a = a[1:]
    60  	}
    61  	if b != "" && b[0] == 'v' {
    62  		b = b[1:]
    63  	}
    64  	var (
    65  		array1 = strings.Split(a, ".")
    66  		array2 = strings.Split(b, ".")
    67  		diff   int
    68  	)
    69  	diff = len(array2) - len(array1)
    70  	for i := 0; i < diff; i++ {
    71  		array1 = append(array1, "0")
    72  	}
    73  	diff = len(array1) - len(array2)
    74  	for i := 0; i < diff; i++ {
    75  		array2 = append(array2, "0")
    76  	}
    77  	v1 := 0
    78  	v2 := 0
    79  	for i := 0; i < len(array1); i++ {
    80  		v1 = gconv.Int(array1[i])
    81  		v2 = gconv.Int(array2[i])
    82  		if v1 > v2 {
    83  			return 1
    84  		}
    85  		if v1 < v2 {
    86  			return -1
    87  		}
    88  	}
    89  	return 0
    90  }
    91  
    92  // CompareVersionGo compares `a` and `b` as standard Golang version.
    93  //
    94  // It returns  1 if `a` > `b`.
    95  //
    96  // It returns -1 if `a` < `b`.
    97  //
    98  // It returns  0 if `a` = `b`.
    99  //
   100  // Golang standard version is like:
   101  // 1.0.0
   102  // v1.0.1
   103  // v2.10.8
   104  // 10.2.0
   105  // v0.0.0-20190626092158-b2ccc519800e
   106  // v1.12.2-0.20200413154443-b17e3a6804fa
   107  // v4.20.0+incompatible
   108  // etc.
   109  //
   110  // Docs: https://go.dev/doc/modules/version-numbers
   111  func CompareVersionGo(a, b string) int {
   112  	a = Trim(a)
   113  	b = Trim(b)
   114  	if a != "" && a[0] == 'v' {
   115  		a = a[1:]
   116  	}
   117  	if b != "" && b[0] == 'v' {
   118  		b = b[1:]
   119  	}
   120  	var (
   121  		rawA = a
   122  		rawB = b
   123  	)
   124  	if Count(a, "-") > 1 {
   125  		if i := PosR(a, "-"); i > 0 {
   126  			a = a[:i]
   127  		}
   128  	}
   129  	if Count(b, "-") > 1 {
   130  		if i := PosR(b, "-"); i > 0 {
   131  			b = b[:i]
   132  		}
   133  	}
   134  	if i := Pos(a, "+"); i > 0 {
   135  		a = a[:i]
   136  	}
   137  	if i := Pos(b, "+"); i > 0 {
   138  		b = b[:i]
   139  	}
   140  	a = Replace(a, "-", ".")
   141  	b = Replace(b, "-", ".")
   142  	var (
   143  		array1 = strings.Split(a, ".")
   144  		array2 = strings.Split(b, ".")
   145  		diff   = len(array1) - len(array2)
   146  	)
   147  
   148  	for i := diff; i < 0; i++ {
   149  		array1 = append(array1, "0")
   150  	}
   151  	for i := 0; i < diff; i++ {
   152  		array2 = append(array2, "0")
   153  	}
   154  
   155  	// check Major.Minor.Patch first
   156  	v1, v2 := 0, 0
   157  	for i := 0; i < len(array1); i++ {
   158  		v1, v2 = gconv.Int(array1[i]), gconv.Int(array2[i])
   159  		// Specially in Golang:
   160  		// "v1.12.2-0.20200413154443-b17e3a6804fa" < "v1.12.2"
   161  		// "v1.12.3-0.20200413154443-b17e3a6804fa" > "v1.12.2"
   162  		if i == 4 && v1 != v2 && (v1 == 0 || v2 == 0) {
   163  			if v1 > v2 {
   164  				return -1
   165  			} else {
   166  				return 1
   167  			}
   168  		}
   169  
   170  		if v1 > v2 {
   171  			return 1
   172  		}
   173  		if v1 < v2 {
   174  			return -1
   175  		}
   176  	}
   177  
   178  	// Specially in Golang:
   179  	// "v4.20.1+incompatible" < "v4.20.1"
   180  	inA, inB := Contains(rawA, "+incompatible"), Contains(rawB, "+incompatible")
   181  	if inA && !inB {
   182  		return -1
   183  	}
   184  	if !inA && inB {
   185  		return 1
   186  	}
   187  
   188  	return 0
   189  }