Files

96 lines
2.2 KiB
Go
Raw Permalink Normal View History

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
}