Updater: Better SemVer version checks for updates
* Instead of a simple "cur. ver != latest ver" check, parse the Major, Minor and Patch components and do a detailed check. * So a x.x.1 release could be made for a specific platform that had a bad build, and it won't mind when it sees the latest version is the older x.x.0 build that other platforms had working fine.
This commit is contained in:
parent
fa15a8bcf5
commit
1105d9312a
|
@ -4,7 +4,7 @@ package branding
|
||||||
const (
|
const (
|
||||||
AppName = "Sketchy Maze"
|
AppName = "Sketchy Maze"
|
||||||
Summary = "A drawing-based maze game"
|
Summary = "A drawing-based maze game"
|
||||||
Version = "0.7.0"
|
Version = "0.7.1"
|
||||||
Website = "https://www.sketchymaze.com"
|
Website = "https://www.sketchymaze.com"
|
||||||
Copyright = "2021 Noah Petherbridge"
|
Copyright = "2021 Noah Petherbridge"
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ func (s *MainScene) checkUpdate() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.LatestVersion != branding.Version {
|
if info.IsNewerVersionThan(branding.Version) {
|
||||||
s.updateInfo = info
|
s.updateInfo = info
|
||||||
s.updateButton.Show()
|
s.updateButton.Show()
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,6 @@ func (s *Supervisor) InstallScripts(level *level.Level) error {
|
||||||
|
|
||||||
// AddLevelScript adds a script to the supervisor with level hooks.
|
// AddLevelScript adds a script to the supervisor with level hooks.
|
||||||
func (s *Supervisor) AddLevelScript(id string) error {
|
func (s *Supervisor) AddLevelScript(id string) error {
|
||||||
log.Debug("InstallScripts: load script from Actor %s", id)
|
|
||||||
|
|
||||||
if _, ok := s.scripts[id]; ok {
|
if _, ok := s.scripts[id]; ok {
|
||||||
return fmt.Errorf("duplicate actor ID %s in level", id)
|
return fmt.Errorf("duplicate actor ID %s in level", id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,6 @@ func (w *Canvas) InstallScripts() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the main() function.
|
// Call the main() function.
|
||||||
log.Debug("Calling Main() for %s", actor.ID())
|
|
||||||
if err := vm.Main(); err != nil {
|
if err := vm.Main(); err != nil {
|
||||||
log.Error("main() for actor %s errored: %s", actor.ID(), err)
|
log.Error("main() for actor %s errored: %s", actor.ID(), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||||
|
@ -18,6 +20,42 @@ type VersionInfo struct {
|
||||||
DownloadURL string `json:"downloadUrl"`
|
DownloadURL string `json:"downloadUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNewerVersionThan checks if the version.json houses a newer
|
||||||
|
// game version than the currently running game's version string.
|
||||||
|
func (i VersionInfo) IsNewerVersionThan(versionString string) bool {
|
||||||
|
// Parse the two semantic versions.
|
||||||
|
curSemver, err := ParseSemver(versionString)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("VersionInfo.IsNewerVersionThan: didn't parse semver: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
latestSemver, err := ParseSemver(i.LatestVersion)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("VersionInfo.IsNewerVersionThan: didn't parse latest semver: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there's a newer version.
|
||||||
|
if latestSemver[Major] > curSemver[Major] {
|
||||||
|
// We're a major version behind, like 0.x.x < 1.x.x
|
||||||
|
return true
|
||||||
|
} else if latestSemver[Major] == curSemver[Major] {
|
||||||
|
// We're on the same major version, like 0.x.x
|
||||||
|
// Check the minor version.
|
||||||
|
if latestSemver[Minor] > curSemver[Minor] {
|
||||||
|
return true
|
||||||
|
} else if latestSemver[Minor] == curSemver[Minor] {
|
||||||
|
// Same minor version, check patch version.
|
||||||
|
if latestSemver[Patch] > curSemver[Patch] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Last result of the update check, until forced to re-check.
|
// Last result of the update check, until forced to re-check.
|
||||||
var lastUpdate VersionInfo
|
var lastUpdate VersionInfo
|
||||||
|
|
||||||
|
@ -61,3 +99,38 @@ func CheckNow() (VersionInfo, error) {
|
||||||
lastUpdate = VersionInfo{}
|
lastUpdate = VersionInfo{}
|
||||||
return Check()
|
return Check()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseSemver parses a Project: Doodle semantic version number into its
|
||||||
|
// three integer parts. Historical versions of the game looked like
|
||||||
|
// either "0.1.0-alpha" or "0.7.0" and the given version string is
|
||||||
|
// expected to match that pattern.
|
||||||
|
func ParseSemver(versionString string) ([3]int, error) {
|
||||||
|
var numbers [3]int
|
||||||
|
result := semverRegexp.FindStringSubmatch(versionString)
|
||||||
|
if result == nil {
|
||||||
|
return numbers, fmt.Errorf("%s: didn't parse as a valid semver string", versionString)
|
||||||
|
}
|
||||||
|
|
||||||
|
// string to int helper
|
||||||
|
var atoi = func(v string) int {
|
||||||
|
a, _ := strconv.Atoi(v)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
numbers = [3]int{
|
||||||
|
atoi(result[1]),
|
||||||
|
atoi(result[2]),
|
||||||
|
atoi(result[3]),
|
||||||
|
}
|
||||||
|
return numbers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var semverRegexp = regexp.MustCompile(`^(\d+)\.(\d+)\.(\d+).*`)
|
||||||
|
|
||||||
|
// Some semantic version indexing constants, to parse the result of
|
||||||
|
// ParseSemver with more semantic code.
|
||||||
|
const (
|
||||||
|
Major int = iota
|
||||||
|
Minor
|
||||||
|
Patch
|
||||||
|
)
|
||||||
|
|
72
pkg/updater/updater_test.go
Normal file
72
pkg/updater/updater_test.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
package updater_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.kirsle.net/apps/doodle/pkg/updater"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test the semver logic.
|
||||||
|
func TestParseSemver(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
A string // version strings
|
||||||
|
B string
|
||||||
|
Expect bool // expect B is newer version than A
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"0.1.0-alpha",
|
||||||
|
"0.1.0-alpha",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.1.0-alpha",
|
||||||
|
"0.2.0-alpha",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.2.0-alpha",
|
||||||
|
"0.2.0-alpha",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.2.0-alpha",
|
||||||
|
"0.1.0-alpha",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.2.0-alpha",
|
||||||
|
"0.2.1-alpha",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.1.0-alpha",
|
||||||
|
"0.2.1-alpha",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.2.1-alpha",
|
||||||
|
"0.3.0",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.3.0",
|
||||||
|
"0.4.1",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.1",
|
||||||
|
"0.2.0",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, test := range tests {
|
||||||
|
result := updater.VersionInfo{
|
||||||
|
LatestVersion: test.B,
|
||||||
|
}.IsNewerVersionThan(test.A)
|
||||||
|
if result != test.Expect {
|
||||||
|
t.Errorf("Test %d: %s <> %s: expected %+v but got %+v",
|
||||||
|
i, test.A, test.B, test.Expect, result,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user