mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 02:51:56 +08:00
feat: better version comparison
This commit is contained in:
parent
11fd50f78d
commit
71194108de
@ -5,34 +5,24 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
)
|
||||
|
||||
// GitHubHelper is a utility class for interacting with GitHub
|
||||
type GitHubHelper struct {
|
||||
validPrereleaseRegex *regexp.Regexp
|
||||
validReleaseRegex *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewGitHubHelper returns a new GitHub Helper
|
||||
func NewGitHubHelper() *GitHubHelper {
|
||||
const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?`
|
||||
const SemPreVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*)`
|
||||
|
||||
return &GitHubHelper{
|
||||
validPrereleaseRegex: regexp.MustCompile(SemPreVerRegex),
|
||||
validReleaseRegex: regexp.MustCompile(SemVerRegex),
|
||||
}
|
||||
return &GitHubHelper{}
|
||||
}
|
||||
|
||||
// GetVersionTags gets the list of tags on the Wails repo
|
||||
// It retuns a list of sorted tags in descending order
|
||||
func (g *GitHubHelper) GetVersionTags() ([]*semver.Version, error) {
|
||||
func (g *GitHubHelper) GetVersionTags() ([]*SemanticVersion, error) {
|
||||
|
||||
result := []*SemanticVersion{}
|
||||
|
||||
result := []*semver.Version{}
|
||||
var err error
|
||||
|
||||
resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/tags")
|
||||
@ -53,7 +43,7 @@ func (g *GitHubHelper) GetVersionTags() ([]*semver.Version, error) {
|
||||
// Convert tag data to Version structs
|
||||
for _, tag := range data {
|
||||
version := tag["name"].(string)
|
||||
semver, err := semver.NewVersion(version)
|
||||
semver, err := NewSemanticVersion(version)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
@ -61,32 +51,41 @@ func (g *GitHubHelper) GetVersionTags() ([]*semver.Version, error) {
|
||||
}
|
||||
|
||||
// Reverse Sort
|
||||
sort.Sort(sort.Reverse(semver.Collection(result)))
|
||||
sort.Sort(sort.Reverse(SemverCollection(result)))
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (g *GitHubHelper) isRelease(tag *semver.Version) bool {
|
||||
return g.validReleaseRegex.MatchString(tag.String())
|
||||
}
|
||||
|
||||
func (g *GitHubHelper) isPreRelease(tag *semver.Version) bool {
|
||||
return g.validPrereleaseRegex.MatchString(tag.String())
|
||||
}
|
||||
|
||||
// GetLatestStableRelease gets the latest stable release on GitHub
|
||||
func (g *GitHubHelper) GetLatestStableRelease() (result string, err error) {
|
||||
func (g *GitHubHelper) GetLatestStableRelease() (result *SemanticVersion, err error) {
|
||||
|
||||
tags, err := g.GetVersionTags()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
if g.isRelease(tag) {
|
||||
return "v" + tag.String(), nil
|
||||
if tag.IsRelease() {
|
||||
return tag, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no release tag found")
|
||||
return nil, fmt.Errorf("no release tag found")
|
||||
}
|
||||
|
||||
// GetLatestPreRelease gets the latest prerelease on GitHub
|
||||
func (g *GitHubHelper) GetLatestPreRelease() (result *SemanticVersion, err error) {
|
||||
|
||||
tags, err := g.GetVersionTags()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
if tag.IsPreRelease() {
|
||||
return tag, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no prerelease tag found")
|
||||
}
|
||||
|
79
cmd/semver.go
Normal file
79
cmd/semver.go
Normal file
@ -0,0 +1,79 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/masterminds/semver"
|
||||
)
|
||||
|
||||
type SemanticVersion struct {
|
||||
Version *semver.Version
|
||||
validPrereleaseRegex *regexp.Regexp
|
||||
validReleaseRegex *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewSemanticVersion creates a new SemanticVersion object with the given version string
|
||||
func NewSemanticVersion(version string) (*SemanticVersion, error) {
|
||||
semverVersion, err := semver.NewVersion(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?`
|
||||
const SemPreVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*)`
|
||||
|
||||
return &SemanticVersion{
|
||||
Version: semverVersion,
|
||||
validPrereleaseRegex: regexp.MustCompile(SemPreVerRegex),
|
||||
validReleaseRegex: regexp.MustCompile(SemVerRegex),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IsRelease returns true if it's a release version
|
||||
func (s *SemanticVersion) IsRelease() bool {
|
||||
return s.validReleaseRegex.MatchString(s.Version.String())
|
||||
}
|
||||
|
||||
// IsPreRelease returns true if it's a prerelease version
|
||||
func (s *SemanticVersion) IsPreRelease() bool {
|
||||
return s.validPrereleaseRegex.MatchString(s.Version.String())
|
||||
}
|
||||
|
||||
func (s *SemanticVersion) String() string {
|
||||
return s.Version.String()
|
||||
}
|
||||
|
||||
func (s *SemanticVersion) IsGreaterThan(version *SemanticVersion) (bool, error) {
|
||||
// Set up new constraint
|
||||
constraint, err := semver.NewConstraint("> " + version.Version.String())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check if the desired one is greater than the requested on
|
||||
success, msgs := constraint.Validate(s.Version)
|
||||
if !success {
|
||||
return false, msgs[0]
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// SemverCollection is a collection of SemanticVersion objects
|
||||
type SemverCollection []*SemanticVersion
|
||||
|
||||
// Len returns the length of a collection. The number of Version instances
|
||||
// on the slice.
|
||||
func (c SemverCollection) Len() int {
|
||||
return len(c)
|
||||
}
|
||||
|
||||
// Less is needed for the sort interface to compare two Version objects on the
|
||||
// slice. If checks if one is less than the other.
|
||||
func (c SemverCollection) Less(i, j int) bool {
|
||||
return c[i].Version.LessThan(c[j].Version)
|
||||
}
|
||||
|
||||
// Swap is needed for the sort interface to replace the Version objects
|
||||
// at two different positions in the slice.
|
||||
func (c SemverCollection) Swap(i, j int) {
|
||||
c[i], c[j] = c[j], c[i]
|
||||
}
|
@ -1,11 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/leaanthony/spinner"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
@ -14,13 +11,16 @@ import (
|
||||
|
||||
func init() {
|
||||
|
||||
var prereleaseRequired bool
|
||||
|
||||
// var forceRebuild = false
|
||||
checkSpinner := spinner.NewSpinner()
|
||||
checkSpinner.SetSpinSpeed(50)
|
||||
|
||||
commandDescription := `This command checks if there are updates to Wails.`
|
||||
commandDescription := `This command allows you to update your version of Wails.`
|
||||
updateCmd := app.Command("update", "Check for Updates.").
|
||||
LongDescription(commandDescription)
|
||||
LongDescription(commandDescription).
|
||||
BoolFlag("pre", "Update to latest Prerelease", &prereleaseRequired)
|
||||
|
||||
updateCmd.Action(func() error {
|
||||
|
||||
@ -30,49 +30,79 @@ func init() {
|
||||
|
||||
// Get versions
|
||||
checkSpinner.Start(message)
|
||||
resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/tags")
|
||||
|
||||
github := cmd.NewGitHubHelper()
|
||||
var desiredVersion *cmd.SemanticVersion
|
||||
var err error
|
||||
|
||||
if prereleaseRequired {
|
||||
desiredVersion, err = github.GetLatestPreRelease()
|
||||
} else {
|
||||
desiredVersion, err = github.GetLatestStableRelease()
|
||||
}
|
||||
if err != nil {
|
||||
checkSpinner.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
checkSpinner.Success()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
checkSpinner.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
data := []map[string]interface{}{}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
latestVersion := data[0]["name"].(string)
|
||||
fmt.Println()
|
||||
fmt.Println("Current Version: " + cmd.Version)
|
||||
fmt.Println(" Latest Version: " + latestVersion)
|
||||
if latestVersion != cmd.Version {
|
||||
updateSpinner := spinner.NewSpinner()
|
||||
updateSpinner.SetSpinSpeed(40)
|
||||
updateSpinner.Start("Updating to : " + latestVersion)
|
||||
|
||||
// Run command in non module directory
|
||||
homeDir, err := homedir.Dir()
|
||||
if err != nil {
|
||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
||||
}
|
||||
|
||||
err = cmd.NewProgramHelper().RunCommandArray([]string{"go", "get", "github.com/wailsapp/wails/.../."}, homeDir)
|
||||
if err != nil {
|
||||
updateSpinner.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
updateSpinner.Success()
|
||||
logger.Yellow("Wails updated to " + latestVersion)
|
||||
fmt.Println(" Current Version : " + cmd.Version)
|
||||
if prereleaseRequired {
|
||||
fmt.Printf(" Latest Prerelease : v%s\n", desiredVersion)
|
||||
} else {
|
||||
logger.Yellow("Looks like you're up to date!")
|
||||
fmt.Printf(" Latest Release : v%s\n", desiredVersion)
|
||||
}
|
||||
return nil
|
||||
|
||||
return updateToVersion(desiredVersion)
|
||||
})
|
||||
}
|
||||
|
||||
func updateToVersion(version *cmd.SemanticVersion) error {
|
||||
|
||||
// Early exit
|
||||
if version.String() == cmd.Version {
|
||||
logger.Green("Looks like you're up to date!")
|
||||
return nil
|
||||
}
|
||||
|
||||
compareVersion := cmd.Version
|
||||
if version.IsPreRelease() {
|
||||
compareVersion += "-0"
|
||||
}
|
||||
|
||||
currentVersion, err := cmd.NewSemanticVersion(compareVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Compare
|
||||
success, err := version.IsGreaterThan(currentVersion)
|
||||
if !success {
|
||||
logger.Red("The requested version is lower than the current version. Aborting.")
|
||||
return nil
|
||||
}
|
||||
|
||||
desiredVersion := "v" + version.String()
|
||||
fmt.Println()
|
||||
updateSpinner := spinner.NewSpinner()
|
||||
updateSpinner.SetSpinSpeed(40)
|
||||
updateSpinner.Start("Installing Wails " + desiredVersion)
|
||||
|
||||
// Run command in non module directory
|
||||
homeDir, err := homedir.Dir()
|
||||
if err != nil {
|
||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
||||
}
|
||||
|
||||
err = cmd.NewProgramHelper().RunCommandArray([]string{"go", "get", "github.com/wailsapp/wails/cmd/wails@" + desiredVersion}, homeDir)
|
||||
if err != nil {
|
||||
updateSpinner.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
updateSpinner.Success()
|
||||
fmt.Println()
|
||||
logger.Green("Wails updated to " + desiredVersion)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user