feat(deploy): 在线更新 - 新增后台检查、强制备份迁移与失败自动回退
This commit is contained in:
79
backend/internal/hostupdate/version.go
Normal file
79
backend/internal/hostupdate/version.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package hostupdate
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type versionPart struct {
|
||||
major, minor, patch int
|
||||
pre []string
|
||||
}
|
||||
|
||||
func CompareVersions(left, right string) int {
|
||||
a, aok := parseVersion(left)
|
||||
b, bok := parseVersion(right)
|
||||
if !aok || !bok {
|
||||
return strings.Compare(strings.TrimSpace(left), strings.TrimSpace(right))
|
||||
}
|
||||
for _, pair := range [][2]int{{a.major, b.major}, {a.minor, b.minor}, {a.patch, b.patch}} {
|
||||
if pair[0] < pair[1] {
|
||||
return -1
|
||||
}
|
||||
if pair[0] > pair[1] {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if len(a.pre) == 0 && len(b.pre) > 0 {
|
||||
return 1
|
||||
}
|
||||
if len(a.pre) > 0 && len(b.pre) == 0 {
|
||||
return -1
|
||||
}
|
||||
for index := 0; index < len(a.pre) || index < len(b.pre); index++ {
|
||||
if index >= len(a.pre) {
|
||||
return -1
|
||||
}
|
||||
if index >= len(b.pre) {
|
||||
return 1
|
||||
}
|
||||
an, aerr := strconv.Atoi(a.pre[index])
|
||||
bn, berr := strconv.Atoi(b.pre[index])
|
||||
switch {
|
||||
case aerr == nil && berr == nil && an < bn:
|
||||
return -1
|
||||
case aerr == nil && berr == nil && an > bn:
|
||||
return 1
|
||||
case aerr == nil && berr != nil:
|
||||
return -1
|
||||
case aerr != nil && berr == nil:
|
||||
return 1
|
||||
case a.pre[index] < b.pre[index]:
|
||||
return -1
|
||||
case a.pre[index] > b.pre[index]:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func parseVersion(raw string) (versionPart, bool) {
|
||||
value := strings.TrimPrefix(strings.TrimSpace(raw), "v")
|
||||
value = strings.SplitN(value, "+", 2)[0]
|
||||
parts := strings.SplitN(value, "-", 2)
|
||||
core := strings.Split(parts[0], ".")
|
||||
if len(core) != 3 {
|
||||
return versionPart{}, false
|
||||
}
|
||||
major, err1 := strconv.Atoi(core[0])
|
||||
minor, err2 := strconv.Atoi(core[1])
|
||||
patch, err3 := strconv.Atoi(core[2])
|
||||
if err1 != nil || err2 != nil || err3 != nil {
|
||||
return versionPart{}, false
|
||||
}
|
||||
parsed := versionPart{major: major, minor: minor, patch: patch}
|
||||
if len(parts) == 2 && parts[1] != "" {
|
||||
parsed.pre = strings.FieldsFunc(parts[1], func(r rune) bool { return r == '.' || r == '-' })
|
||||
}
|
||||
return parsed, true
|
||||
}
|
||||
Reference in New Issue
Block a user