diff --git a/updater/file.go b/updater/file.go index 88e044a..1ad76f0 100644 --- a/updater/file.go +++ b/updater/file.go @@ -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 diff --git a/updater/resource.go b/updater/resource.go index cf46ff8..4476cdb 100644 --- a/updater/resource.go +++ b/updater/resource.go @@ -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 { diff --git a/updater/resource_test.go b/updater/resource_test.go index f6bc4a6..2f734cc 100644 --- a/updater/resource_test.go +++ b/updater/resource_test.go @@ -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() +}