gstr_version.go 3.4 KB

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