mirror of
https://github.com/OpenFactorioServerManager/factorio-server-manager.git
synced 2025-01-08 04:04:53 +02:00
Merge pull request #126 from sean-callahan/develop
fix #123: incorrect incompatibility flags
This commit is contained in:
commit
663bd85805
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
17
src/mods.go
17
src/mods.go
@ -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
81
src/version.go
Normal 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")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user