mirror of
https://github.com/OpenFactorioServerManager/factorio-server-manager.git
synced 2025-01-24 05:17:24 +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"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/majormjr/rcon"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"github.com/Masterminds/semver"
|
|
||||||
|
"github.com/majormjr/rcon"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FactorioServer struct {
|
type FactorioServer struct {
|
||||||
@ -28,9 +28,8 @@ type FactorioServer struct {
|
|||||||
BindIP string `json:"bindip"`
|
BindIP string `json:"bindip"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
Running bool `json:"running"`
|
Running bool `json:"running"`
|
||||||
Version string `json:"fac_version"`
|
Version Version `json:"fac_version"`
|
||||||
BaseModVersion string `json:"base_mod_version"`
|
BaseModVersion string `json:"base_mod_version"`
|
||||||
SemVerVersion *semver.Version `json:"-"`
|
|
||||||
StdOut io.ReadCloser `json:"-"`
|
StdOut io.ReadCloser `json:"-"`
|
||||||
StdErr io.ReadCloser `json:"-"`
|
StdErr io.ReadCloser `json:"-"`
|
||||||
StdIn io.WriteCloser `json:"-"`
|
StdIn io.WriteCloser `json:"-"`
|
||||||
@ -97,7 +96,6 @@ func initFactorio() (f *FactorioServer, err error) {
|
|||||||
|
|
||||||
log.Printf("Loaded Factorio settings from %s\n", settingsPath)
|
log.Printf("Loaded Factorio settings from %s\n", settingsPath)
|
||||||
|
|
||||||
|
|
||||||
//Load factorio version
|
//Load factorio version
|
||||||
out, err := exec.Command(config.FactorioBinary, "--version").Output()
|
out, err := exec.Command(config.FactorioBinary, "--version").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -107,7 +105,11 @@ func initFactorio() (f *FactorioServer, err error) {
|
|||||||
|
|
||||||
reg := regexp.MustCompile("Version.*?((\\d+\\.)?(\\d+\\.)?(\\*|\\d+)+)")
|
reg := regexp.MustCompile("Version.*?((\\d+\\.)?(\\d+\\.)?(\\*|\\d+)+)")
|
||||||
found := reg.FindStringSubmatch(string(out))
|
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
|
//Load baseMod version
|
||||||
baseModInfoFile := filepath.Join(config.FactorioDir, "data", "base", "info.json")
|
baseModInfoFile := filepath.Join(config.FactorioDir, "data", "base", "info.json")
|
||||||
@ -124,10 +126,6 @@ func initFactorio() (f *FactorioServer, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.BaseModVersion = modInfo.Version
|
f.BaseModVersion = modInfo.Version
|
||||||
f.SemVerVersion, err = semver.NewVersion(modInfo.Version)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error loading semver-factorio-version: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
@ -12,6 +11,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JSONResponse struct {
|
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")
|
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||||
|
|
||||||
status := map[string]string{}
|
status := map[string]string{}
|
||||||
status["version"] = FactorioServ.Version
|
status["version"] = FactorioServ.Version.String()
|
||||||
status["base_mod_version"] = FactorioServ.BaseModVersion
|
status["base_mod_version"] = FactorioServ.BaseModVersion
|
||||||
|
|
||||||
resp.Data = status
|
resp.Data = status
|
||||||
|
@ -18,14 +18,14 @@ type ModInfoList struct {
|
|||||||
Destination string `json:"-"`
|
Destination string `json:"-"`
|
||||||
}
|
}
|
||||||
type ModInfo struct {
|
type ModInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Author string `json:"author"`
|
Author string `json:"author"`
|
||||||
FileName string `json:"file_name"`
|
FileName string `json:"file_name"`
|
||||||
FactorioVersion string `json:"factorio_version"`
|
FactorioVersion Version `json:"factorio_version"`
|
||||||
Dependencies []string `json:"dependencies"`
|
Dependencies []string `json:"dependencies"`
|
||||||
Compatibility bool `json:"compatibility"`
|
Compatibility bool `json:"compatibility"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newModInfoList(destination string) (ModInfoList, error) {
|
func newModInfoList(destination string) (ModInfoList, error) {
|
||||||
@ -74,33 +74,43 @@ func (modInfoList *ModInfoList) listInstalledMods() error {
|
|||||||
|
|
||||||
modInfo.FileName = info.Name()
|
modInfo.FileName = info.Name()
|
||||||
|
|
||||||
var baseDependency string
|
var base Version
|
||||||
for _, dependency := range modInfo.Dependencies {
|
var op string
|
||||||
if strings.HasPrefix(dependency, "base") {
|
for _, dep := range modInfo.Dependencies {
|
||||||
splittedDep := strings.Split(dependency, "=")
|
dep = strings.TrimSpace(dep)
|
||||||
|
if dep == "" {
|
||||||
if len(splittedDep) == 1 {
|
continue
|
||||||
log.Printf("basemod without version specified!")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
baseDependency = strings.Split(dependency, "=")[1]
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 !base.Equals(NilVersion) {
|
||||||
if err != nil {
|
modInfo.Compatibility = FactorioServ.Version.Compare(base, op)
|
||||||
log.Printf("error checking mod compatibility: %s", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
log.Println("error finding basemodDependency. Using FactorioVersion...")
|
log.Println("error finding basemodDependency. Using FactorioVersion...")
|
||||||
modInfo.Compatibility, err = checkModCompatibility(modInfo.FactorioVersion + ".0")
|
modInfo.Compatibility = !FactorioServ.Version.Less(modInfo.FactorioVersion)
|
||||||
if err != nil {
|
|
||||||
log.Printf("error checking Compatibility with FactorioVersion: %s", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
modInfoList.Mods = append(modInfoList.Mods, modInfo)
|
modInfoList.Mods = append(modInfoList.Mods, modInfo)
|
||||||
|
17
src/mods.go
17
src/mods.go
@ -12,7 +12,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"github.com/Masterminds/semver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoginErrorResponse struct {
|
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…
x
Reference in New Issue
Block a user