c9a88afcef
New selfupdate package: version parsing, audit state file, updater with
Gitea registry V2 check, docker pull + compose rewrite + compose up flow.
- API: /api/selfupdate/{status,check,update} with session+bearer auth
- UI: Settings "Verzió és frissítés" card with check/install buttons + JS polling
- Scheduler: periodic check (6h default) + optional daily auto-update
- Notifications: success/failure on post-update startup verification
- Alert: info banner when update available
- docker-compose.yml: add directory bind mount for compose file access
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
69 lines
1.5 KiB
Go
69 lines
1.5 KiB
Go
package selfupdate
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Version represents a semantic version (Major.Minor.Patch).
|
|
type Version struct {
|
|
Major int
|
|
Minor int
|
|
Patch int
|
|
Raw string
|
|
}
|
|
|
|
// ParseVersion parses "X.Y.Z" or "vX.Y.Z". Returns error for "dev", "latest", or invalid formats.
|
|
func ParseVersion(s string) (Version, error) {
|
|
s = strings.TrimPrefix(s, "v")
|
|
if s == "dev" || s == "latest" || s == "" {
|
|
return Version{}, fmt.Errorf("invalid version: %q", s)
|
|
}
|
|
parts := strings.SplitN(s, ".", 3)
|
|
if len(parts) != 3 {
|
|
return Version{}, fmt.Errorf("invalid version format: %q (expected X.Y.Z)", s)
|
|
}
|
|
major, err := strconv.Atoi(parts[0])
|
|
if err != nil {
|
|
return Version{}, fmt.Errorf("invalid major version: %w", err)
|
|
}
|
|
minor, err := strconv.Atoi(parts[1])
|
|
if err != nil {
|
|
return Version{}, fmt.Errorf("invalid minor version: %w", err)
|
|
}
|
|
patch, err := strconv.Atoi(parts[2])
|
|
if err != nil {
|
|
return Version{}, fmt.Errorf("invalid patch version: %w", err)
|
|
}
|
|
return Version{Major: major, Minor: minor, Patch: patch, Raw: s}, nil
|
|
}
|
|
|
|
// Compare returns -1 if a < b, 0 if a == b, 1 if a > b.
|
|
func (a Version) Compare(b Version) int {
|
|
if a.Major != b.Major {
|
|
if a.Major < b.Major {
|
|
return -1
|
|
}
|
|
return 1
|
|
}
|
|
if a.Minor != b.Minor {
|
|
if a.Minor < b.Minor {
|
|
return -1
|
|
}
|
|
return 1
|
|
}
|
|
if a.Patch != b.Patch {
|
|
if a.Patch < b.Patch {
|
|
return -1
|
|
}
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// String returns the version as "X.Y.Z".
|
|
func (v Version) String() string {
|
|
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
|
}
|