Files
LocalAI/pkg/addons/contract/version.go
T
Ettore Di Giacinto d537695895 feat(addons): write one add-on package as a zip
Add the zip format of a package (a digest manifest plus the files of the
OCI package for one platform) and an addonpkg zip subcommand that writes
it from a verified layout, with a sha256 file. The zip comes from the
same layout the registry package comes from, so there is one build path.

Version comparison moves to contract.CompareVersions so the installer
can use it for upgrades and downgrades.

Assisted-by: Claude:claude-sonnet-5-5 go gofmt
2026-11-03 22:52:50 +00:00

88 lines
1.5 KiB
Go

// SPDX-License-Identifier: MIT
package contract
import "strings"
// CompareVersions orders two add-on versions by semantic versioning: it
// returns -1, 0 or 1. A pre-release sorts below its release. Build metadata
// does not occur in an add-on version.
func CompareVersions(a, b string) int {
pa, pb := splitVersion(a), splitVersion(b)
for i := 0; i < 3; i++ {
if pa.num[i] != pb.num[i] {
if pa.num[i] < pb.num[i] {
return -1
}
return 1
}
}
switch {
case pa.pre == "" && pb.pre == "":
return 0
case pa.pre == "":
return 1
case pb.pre == "":
return -1
}
as, bs := strings.Split(pa.pre, "."), strings.Split(pb.pre, ".")
for i := 0; i < len(as) && i < len(bs); i++ {
if as[i] == bs[i] {
continue
}
an, aok := atoiBounded(as[i])
bn, bok := atoiBounded(bs[i])
switch {
case aok && bok:
if an < bn {
return -1
}
return 1
case aok:
return -1
case bok:
return 1
case as[i] < bs[i]:
return -1
default:
return 1
}
}
switch {
case len(as) < len(bs):
return -1
case len(as) > len(bs):
return 1
}
return 0
}
type parsedVersion struct {
num [3]int
pre string
}
func splitVersion(v string) parsedVersion {
core, pre, _ := strings.Cut(v, "-")
var s parsedVersion
for i, p := range strings.SplitN(core, ".", 3) {
n, _ := atoiBounded(p)
s.num[i] = n
}
s.pre = pre
return s
}
func atoiBounded(s string) (int, bool) {
if s == "" {
return 0, false
}
n := 0
for _, r := range s {
if r < '0' || r > '9' || n > 1<<40 {
return 0, false
}
n = n*10 + int(r-'0')
}
return n, true
}