This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package updater
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Phase string
|
||||
|
||||
const (
|
||||
PhaseIdle Phase = "idle"
|
||||
PhaseScheduled Phase = "scheduled"
|
||||
PhaseRunning Phase = "running"
|
||||
PhaseSuccess Phase = "success"
|
||||
PhaseFailed Phase = "failed"
|
||||
)
|
||||
|
||||
// Status 是主程序与 fonu-updater sidecar 共享的更新状态。
|
||||
type Status struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Mode string `json:"mode"`
|
||||
CurrentVersion string `json:"current_version,omitempty"`
|
||||
LatestVersion string `json:"latest_version,omitempty"`
|
||||
UpdateAvailable bool `json:"update_available"`
|
||||
Busy bool `json:"busy"`
|
||||
Phase Phase `json:"phase"`
|
||||
Message string `json:"message"`
|
||||
Log []string `json:"log,omitempty"`
|
||||
CheckedAt string `json:"checked_at,omitempty"`
|
||||
}
|
||||
|
||||
func busyPhase(phase Phase) bool {
|
||||
return phase == PhaseScheduled || phase == PhaseRunning
|
||||
}
|
||||
|
||||
// CompareVersions 比较形如 1.2.3、v1.2.3 的版本号;返回值大于 0 表示 a 更新。
|
||||
func CompareVersions(a, b string) int {
|
||||
left := parseVersion(a)
|
||||
right := parseVersion(b)
|
||||
length := len(left)
|
||||
if len(right) > length {
|
||||
length = len(right)
|
||||
}
|
||||
for index := 0; index < length; index++ {
|
||||
var lv, rv int
|
||||
if index < len(left) {
|
||||
lv = left[index]
|
||||
}
|
||||
if index < len(right) {
|
||||
rv = right[index]
|
||||
}
|
||||
if lv != rv {
|
||||
if lv > rv {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func parseVersion(value string) []int {
|
||||
clean := strings.TrimSpace(strings.TrimPrefix(value, "v"))
|
||||
if index := strings.IndexAny(clean, "-+"); index >= 0 {
|
||||
clean = clean[:index]
|
||||
}
|
||||
parts := strings.Split(clean, ".")
|
||||
out := make([]int, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
number, err := strconv.Atoi(part)
|
||||
if err != nil {
|
||||
out = append(out, 0)
|
||||
continue
|
||||
}
|
||||
out = append(out, number)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func validateSemver(value string) error {
|
||||
if value == "" {
|
||||
return fmt.Errorf("版本号为空")
|
||||
}
|
||||
parts := strings.Split(strings.TrimPrefix(value, "v"), ".")
|
||||
if len(parts) != 3 {
|
||||
return fmt.Errorf("版本号格式无效: %s", value)
|
||||
}
|
||||
for _, part := range parts {
|
||||
if _, err := strconv.Atoi(part); err != nil {
|
||||
return fmt.Errorf("版本号格式无效: %s", value)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user