Use semver normalized version strings and add semver util functions

This commit is contained in:
Daniel 2021-03-10 14:02:35 +01:00
parent 566c8fe719
commit bb660bc901
3 changed files with 72 additions and 4 deletions

View file

@ -7,6 +7,8 @@ import (
"github.com/safing/portbase/log"
"github.com/safing/portbase/utils"
semver "github.com/hashicorp/go-version"
)
// File represents a file from the update system.
@ -28,6 +30,16 @@ func (file *File) Version() string {
return file.version.VersionNumber
}
// SemVer returns the semantic version of the file.
func (file *File) SemVer() *semver.Version {
return file.version.semVer
}
// EqualsVersion normalizes the given version and checks equality with semver.
func (file *File) EqualsVersion(version string) bool {
return file.version.EqualsVersion(version)
}
// Path returns the absolute filepath of the file.
func (file *File) Path() string {
return file.storagePath

View file

@ -13,6 +13,18 @@ import (
semver "github.com/hashicorp/go-version"
)
var (
devVersion *semver.Version
)
func init() {
var err error
devVersion, err = semver.NewVersion("0")
if err != nil {
panic(err)
}
}
// Resource represents a resource (via an identifier) and multiple file versions.
type Resource struct {
sync.Mutex
@ -71,6 +83,21 @@ func (rv *ResourceVersion) String() string {
return rv.VersionNumber
}
// SemVer returns the semantiv version of the resource.
func (rv *ResourceVersion) SemVer() *semver.Version {
return rv.semVer
}
// EqualsVersion normalizes the given version and checks equality with semver.
func (rv *ResourceVersion) EqualsVersion(version string) bool {
cmpSemVer, err := semver.NewVersion(version)
if err != nil {
return false
}
return rv.semVer.Equal(cmpSemVer)
}
// isSelectable returns true if the version represented by rv is selectable.
// A version is selectable if it's not blacklisted and either already locally
// available or ready to be downloaded.
@ -85,7 +112,12 @@ func (rv *ResourceVersion) isBetaVersionNumber() bool {
// new versions should use the pre-release suffix as
// declared by https://semver.org
// i.e. 1.2.3-beta
return strings.HasSuffix(rv.VersionNumber, "b") || strings.Contains(rv.semVer.Prerelease(), "beta")
switch rv.semVer.Prerelease() {
case "b", "beta":
return true
default:
return false
}
}
// Len is the number of elements in the collection.
@ -175,7 +207,7 @@ func (res *Resource) AddVersion(version string, available, stableRelease, betaRe
rv = &ResourceVersion{
resource: res,
VersionNumber: version,
VersionNumber: sv.String(), // Use normalized version.
semVer: sv,
}
res.Versions = append(res.Versions, rv)
@ -253,7 +285,7 @@ func (res *Resource) selectVersion() {
// get last element
rv := res.Versions[len(res.Versions)-1]
// check if it's a dev version
if rv.VersionNumber == "0" && rv.Available {
if rv.semVer.Equal(devVersion) && rv.Available {
res.SelectedVersion = rv
return
}
@ -312,7 +344,7 @@ func (res *Resource) Blacklist(version string) error {
// count available and valid versions
valid := 0
for _, rv := range res.Versions {
if rv.VersionNumber == "0" {
if rv.semVer.Equal(devVersion) {
continue // ignore dev versions
}
if !rv.Blacklisted {

View file

@ -1,7 +1,11 @@
package updater
import (
"fmt"
"testing"
semver "github.com/hashicorp/go-version"
"github.com/stretchr/testify/assert"
)
func TestVersionSelection(t *testing.T) {
@ -79,3 +83,23 @@ func TestVersionSelection(t *testing.T) {
t.Logf("version %s: %+v", rv.VersionNumber, rv)
}
}
func TestVersionParsing(t *testing.T) {
assert.Equal(t, "1.2.3", parseVersion("1.2.3"))
assert.Equal(t, "1.2.0", parseVersion("1.2.0"))
assert.Equal(t, "0.2.0", parseVersion("0.2.0"))
assert.Equal(t, "0.0.0", parseVersion("0"))
assert.Equal(t, "1.2.3-b", parseVersion("1.2.3-b"))
assert.Equal(t, "1.2.3-b", parseVersion("1.2.3b"))
assert.Equal(t, "1.2.3-beta", parseVersion("1.2.3-beta"))
assert.Equal(t, "1.2.3-beta", parseVersion("1.2.3beta"))
assert.Equal(t, "1.2.3", parseVersion("01.02.03"))
}
func parseVersion(v string) string {
sv, err := semver.NewVersion(v)
if err != nil {
return fmt.Sprintf("failed to parse version: %s", err)
}
return sv.String()
}