Merge pull request #126 from sean-callahan/develop

fix #123: incorrect incompatibility flags
This commit is contained in:
Mitch Roote 2019-01-09 17:56:26 -05:00 committed by GitHub
commit 663bd85805
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 133 additions and 60 deletions

View File

@ -16,9 +16,9 @@ import (
"strings"
"time"
"github.com/majormjr/rcon"
"regexp"
"github.com/Masterminds/semver"
"github.com/majormjr/rcon"
)
type FactorioServer struct {
@ -28,9 +28,8 @@ type FactorioServer struct {
BindIP string `json:"bindip"`
Port int `json:"port"`
Running bool `json:"running"`
Version string `json:"fac_version"`
Version Version `json:"fac_version"`
BaseModVersion string `json:"base_mod_version"`
SemVerVersion *semver.Version `json:"-"`
StdOut io.ReadCloser `json:"-"`
StdErr io.ReadCloser `json:"-"`
StdIn io.WriteCloser `json:"-"`
@ -97,7 +96,6 @@ func initFactorio() (f *FactorioServer, err error) {
log.Printf("Loaded Factorio settings from %s\n", settingsPath)
//Load factorio version
out, err := exec.Command(config.FactorioBinary, "--version").Output()
if err != nil {
@ -107,7 +105,11 @@ func initFactorio() (f *FactorioServer, err error) {
reg := regexp.MustCompile("Version.*?((\\d+\\.)?(\\d+\\.)?(\\*|\\d+)+)")
found := reg.FindStringSubmatch(string(out))
f.Version = found[1]
err = f.Version.UnmarshalText([]byte(found[1]))
if err != nil {
log.Printf("could not parse version: %v", err)
return
}
//Load baseMod version
baseModInfoFile := filepath.Join(config.FactorioDir, "data", "base", "info.json")
@ -124,10 +126,6 @@ func initFactorio() (f *FactorioServer, err error) {
}
f.BaseModVersion = modInfo.Version
f.SemVerVersion, err = semver.NewVersion(modInfo.Version)
if err != nil {
log.Fatalf("error loading semver-factorio-version: %s", err)
}
return
}

View File

@ -3,7 +3,6 @@ package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"io"
"io/ioutil"
"log"
@ -12,6 +11,8 @@ import (
"path/filepath"
"strconv"
"time"
"github.com/gorilla/mux"
)
type JSONResponse struct {
@ -443,7 +444,7 @@ func FactorioVersion(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
status := map[string]string{}
status["version"] = FactorioServ.Version
status["version"] = FactorioServ.Version.String()
status["base_mod_version"] = FactorioServ.BaseModVersion
resp.Data = status

View File

@ -18,14 +18,14 @@ type ModInfoList struct {
Destination string `json:"-"`
}
type ModInfo struct {
Name string `json:"name"`
Version string `json:"version"`
Title string `json:"title"`
Author string `json:"author"`
FileName string `json:"file_name"`
FactorioVersion string `json:"factorio_version"`
Dependencies []string `json:"dependencies"`
Compatibility bool `json:"compatibility"`
Name string `json:"name"`
Version string `json:"version"`
Title string `json:"title"`
Author string `json:"author"`
FileName string `json:"file_name"`
FactorioVersion Version `json:"factorio_version"`
Dependencies []string `json:"dependencies"`
Compatibility bool `json:"compatibility"`
}
func newModInfoList(destination string) (ModInfoList, error) {
@ -74,33 +74,43 @@ func (modInfoList *ModInfoList) listInstalledMods() error {
modInfo.FileName = info.Name()
var baseDependency string
for _, dependency := range modInfo.Dependencies {
if strings.HasPrefix(dependency, "base") {
splittedDep := strings.Split(dependency, "=")
if len(splittedDep) == 1 {
log.Printf("basemod without version specified!")
break
}
baseDependency = strings.Split(dependency, "=")[1]
break
var base Version
var op string
for _, dep := range modInfo.Dependencies {
dep = strings.TrimSpace(dep)
if dep == "" {
continue
}
parts := strings.Split(dep, " ")
if len(parts) > 3 {
log.Printf("skipping dependency '%s' in '%s': invalid format\n", dep, modInfo.Name)
continue
}
if parts[0] != "base" {
continue
}
if len(parts) == 1 {
base = modInfo.FactorioVersion
op = ">="
continue
}
op = parts[1]
if err := base.UnmarshalText([]byte(parts[2])); err != nil {
log.Printf("skipping dependency '%s' in '%s': %v\n", dep, modInfo.Name, err)
continue
}
break
}
if baseDependency != "" {
modInfo.Compatibility, err = checkModCompatibility(baseDependency)
if err != nil {
log.Printf("error checking mod compatibility: %s", err)
return err
}
if !base.Equals(NilVersion) {
modInfo.Compatibility = FactorioServ.Version.Compare(base, op)
} else {
log.Println("error finding basemodDependency. Using FactorioVersion...")
modInfo.Compatibility, err = checkModCompatibility(modInfo.FactorioVersion + ".0")
if err != nil {
log.Printf("error checking Compatibility with FactorioVersion: %s", err)
return err
}
modInfo.Compatibility = !FactorioServ.Version.Less(modInfo.FactorioVersion)
}
modInfoList.Mods = append(modInfoList.Mods, modInfo)

View File

@ -12,7 +12,6 @@ import (
"os"
"path/filepath"
"strings"
"github.com/Masterminds/semver"
)
type LoginErrorResponse struct {
@ -345,19 +344,3 @@ func modStartUp() {
}
}
}
func checkModCompatibility(modVersion string) (compatible bool, err error) {
compatible = false
modVersion = strings.TrimSpace(modVersion)
if !strings.HasPrefix(modVersion, "~") {
modVersion = "~" + modVersion
}
constraint, err := semver.NewConstraint(modVersion)
if err != nil {
log.Printf("error loading constraint: %s", err)
return
}
return constraint.Check(FactorioServ.SemVerVersion), nil
}

81
src/version.go Normal file
View File

@ -0,0 +1,81 @@
package main
import (
"fmt"
"strconv"
"strings"
)
// NilVersion represents an empty version number
var NilVersion = Version{0, 0, 0}
// Version represents a semantic version
type Version [3]uint
func (v Version) String() string {
return fmt.Sprintf("%d.%d.%d", v[0], v[1], v[2])
}
// MarshalText implements encoding.TextMarshaller for Version
func (v Version) MarshalText() (text []byte, err error) {
return []byte(v.String()), nil
}
// UnmarshalText implements encoding.TextUnmarshaller for Version
func (v *Version) UnmarshalText(text []byte) error {
parts := strings.SplitN(string(text), ".", 3)
for i, part := range parts {
p, err := strconv.ParseUint(part, 10, 32)
if err != nil {
return err
}
v[i] = uint(p)
}
return nil
}
// Equals returns true if both version are equal
func (v Version) Equals(b Version) bool {
return v[0] == b[0] && v[1] == b[1] && v[2] == b[2]
}
// Less returns true if the receiver version is less than the argument version
func (v Version) Less(b Version) bool {
switch {
case v[0] < b[0]:
return true
case v[0] == b[0] && v[1] < b[1]:
return true
case v[0] == b[0] && v[1] == b[1] && v[2] < b[2]:
return true
default:
return false
}
}
// Greater returns true if the receiver version is greater than the argument version
func (v Version) Greater(b Version) bool { return !v.Equals(b) && !v.Less(b) }
func (v Version) ge(b Version) bool { return v.Equals(b) || v.Greater(b) }
func (v Version) le(b Version) bool { return v.Equals(b) || v.Less(b) }
// Compare returns true if the comparison between the two version operands is valid.
// Supported ops are: ==, !=, >, <, >=, <=
func (v Version) Compare(b Version, op string) bool {
switch op {
case "==":
return v.Equals(b)
case "!=":
return !v.Equals(b)
case ">":
return v.Greater(b)
case "<":
return v.Less(b)
case ">=":
return v.ge(b)
case "<=":
return v.le(b)
default:
panic("unsupported operator")
}
}