version.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package badversion
  2. import (
  3. "strconv"
  4. "strings"
  5. F "github.com/sagernet/sing/common/format"
  6. "golang.org/x/mod/semver"
  7. )
  8. type Version struct {
  9. Major int
  10. Minor int
  11. Patch int
  12. Commit string
  13. PreReleaseIdentifier string
  14. PreReleaseVersion int
  15. }
  16. func (v Version) LessThan(anotherVersion Version) bool {
  17. return !v.GreaterThanOrEqual(anotherVersion)
  18. }
  19. func (v Version) LessThanOrEqual(anotherVersion Version) bool {
  20. return v == anotherVersion || anotherVersion.GreaterThan(v)
  21. }
  22. func (v Version) GreaterThanOrEqual(anotherVersion Version) bool {
  23. return v == anotherVersion || v.GreaterThan(anotherVersion)
  24. }
  25. func (v Version) GreaterThan(anotherVersion Version) bool {
  26. if v.Major > anotherVersion.Major {
  27. return true
  28. } else if v.Major < anotherVersion.Major {
  29. return false
  30. }
  31. if v.Minor > anotherVersion.Minor {
  32. return true
  33. } else if v.Minor < anotherVersion.Minor {
  34. return false
  35. }
  36. if v.Patch > anotherVersion.Patch {
  37. return true
  38. } else if v.Patch < anotherVersion.Patch {
  39. return false
  40. }
  41. if v.PreReleaseIdentifier == "" && anotherVersion.PreReleaseIdentifier != "" {
  42. return true
  43. } else if v.PreReleaseIdentifier != "" && anotherVersion.PreReleaseIdentifier == "" {
  44. return false
  45. }
  46. if v.PreReleaseIdentifier != "" && anotherVersion.PreReleaseIdentifier != "" {
  47. if v.PreReleaseIdentifier == anotherVersion.PreReleaseIdentifier {
  48. if v.PreReleaseVersion > anotherVersion.PreReleaseVersion {
  49. return true
  50. } else if v.PreReleaseVersion < anotherVersion.PreReleaseVersion {
  51. return false
  52. }
  53. }
  54. preReleaseIdentifier := parsePreReleaseIdentifier(v.PreReleaseIdentifier)
  55. anotherPreReleaseIdentifier := parsePreReleaseIdentifier(anotherVersion.PreReleaseIdentifier)
  56. if preReleaseIdentifier < anotherPreReleaseIdentifier {
  57. return true
  58. } else if preReleaseIdentifier > anotherPreReleaseIdentifier {
  59. return false
  60. }
  61. }
  62. return false
  63. }
  64. func parsePreReleaseIdentifier(identifier string) int {
  65. if strings.HasPrefix(identifier, "rc") {
  66. return 1
  67. } else if strings.HasPrefix(identifier, "beta") {
  68. return 2
  69. } else if strings.HasPrefix(identifier, "alpha") {
  70. return 3
  71. }
  72. return 0
  73. }
  74. func (v Version) VersionString() string {
  75. return F.ToString(v.Major, ".", v.Minor, ".", v.Patch)
  76. }
  77. func (v Version) String() string {
  78. version := F.ToString(v.Major, ".", v.Minor, ".", v.Patch)
  79. if v.PreReleaseIdentifier != "" {
  80. version = F.ToString(version, "-", v.PreReleaseIdentifier, ".", v.PreReleaseVersion)
  81. }
  82. return version
  83. }
  84. func (v Version) BadString() string {
  85. version := F.ToString(v.Major, ".", v.Minor)
  86. if v.Patch > 0 {
  87. version = F.ToString(version, ".", v.Patch)
  88. }
  89. if v.PreReleaseIdentifier != "" {
  90. version = F.ToString(version, "-", v.PreReleaseIdentifier)
  91. if v.PreReleaseVersion > 0 {
  92. version = F.ToString(version, v.PreReleaseVersion)
  93. }
  94. }
  95. return version
  96. }
  97. func IsValid(versionName string) bool {
  98. return semver.IsValid("v" + versionName)
  99. }
  100. func Parse(versionName string) (version Version) {
  101. if strings.HasPrefix(versionName, "v") {
  102. versionName = versionName[1:]
  103. }
  104. if strings.Contains(versionName, "-") {
  105. parts := strings.Split(versionName, "-")
  106. versionName = parts[0]
  107. identifier := parts[1]
  108. if strings.Contains(identifier, ".") {
  109. identifierParts := strings.Split(identifier, ".")
  110. version.PreReleaseIdentifier = identifierParts[0]
  111. if len(identifierParts) >= 2 {
  112. version.PreReleaseVersion, _ = strconv.Atoi(identifierParts[1])
  113. }
  114. } else {
  115. if strings.HasPrefix(identifier, "alpha") {
  116. version.PreReleaseIdentifier = "alpha"
  117. version.PreReleaseVersion, _ = strconv.Atoi(identifier[5:])
  118. } else if strings.HasPrefix(identifier, "beta") {
  119. version.PreReleaseIdentifier = "beta"
  120. version.PreReleaseVersion, _ = strconv.Atoi(identifier[4:])
  121. } else {
  122. version.Commit = identifier
  123. }
  124. }
  125. }
  126. versionElements := strings.Split(versionName, ".")
  127. versionLen := len(versionElements)
  128. if versionLen >= 1 {
  129. version.Major, _ = strconv.Atoi(versionElements[0])
  130. }
  131. if versionLen >= 2 {
  132. version.Minor, _ = strconv.Atoi(versionElements[1])
  133. }
  134. if versionLen >= 3 {
  135. version.Patch, _ = strconv.Atoi(versionElements[2])
  136. }
  137. return
  138. }