Skip to content

Commit 637acba

Browse files
committed
fix #123: incorrect incompatiblity flags
Added a new Version type to wean off of the vendored semver library. Simplified base dependency checking for mod.json
1 parent 807950a commit 637acba

File tree

5 files changed

+97
-58
lines changed

5 files changed

+97
-58
lines changed

src/factorio_server.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import (
1616
"strings"
1717
"time"
1818

19-
"github.com/majormjr/rcon"
2019
"regexp"
21-
"github.com/Masterminds/semver"
20+
21+
"github.com/majormjr/rcon"
2222
)
2323

2424
type FactorioServer struct {
@@ -28,9 +28,8 @@ type FactorioServer struct {
2828
BindIP string `json:"bindip"`
2929
Port int `json:"port"`
3030
Running bool `json:"running"`
31-
Version string `json:"fac_version"`
31+
Version Version `json:"fac_version"`
3232
BaseModVersion string `json:"base_mod_version"`
33-
SemVerVersion *semver.Version `json:"-"`
3433
StdOut io.ReadCloser `json:"-"`
3534
StdErr io.ReadCloser `json:"-"`
3635
StdIn io.WriteCloser `json:"-"`
@@ -97,7 +96,6 @@ func initFactorio() (f *FactorioServer, err error) {
9796

9897
log.Printf("Loaded Factorio settings from %s\n", settingsPath)
9998

100-
10199
//Load factorio version
102100
out, err := exec.Command(config.FactorioBinary, "--version").Output()
103101
if err != nil {
@@ -107,7 +105,11 @@ func initFactorio() (f *FactorioServer, err error) {
107105

108106
reg := regexp.MustCompile("Version.*?((\\d+\\.)?(\\d+\\.)?(\\*|\\d+)+)")
109107
found := reg.FindStringSubmatch(string(out))
110-
f.Version = found[1]
108+
err = f.Version.UnmarshalText([]byte(found[1]))
109+
if err != nil {
110+
log.Printf("could not parse version: %v", err)
111+
return
112+
}
111113

112114
//Load baseMod version
113115
baseModInfoFile := filepath.Join(config.FactorioDir, "data", "base", "info.json")
@@ -124,10 +126,6 @@ func initFactorio() (f *FactorioServer, err error) {
124126
}
125127

126128
f.BaseModVersion = modInfo.Version
127-
f.SemVerVersion, err = semver.NewVersion(modInfo.Version)
128-
if err != nil {
129-
log.Fatalf("error loading semver-factorio-version: %s", err)
130-
}
131129

132130
return
133131
}

src/handlers.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"encoding/json"
55
"fmt"
6-
"github.com/gorilla/mux"
76
"io"
87
"io/ioutil"
98
"log"
@@ -12,6 +11,8 @@ import (
1211
"path/filepath"
1312
"strconv"
1413
"time"
14+
15+
"github.com/gorilla/mux"
1516
)
1617

1718
type JSONResponse struct {
@@ -443,7 +444,7 @@ func FactorioVersion(w http.ResponseWriter, r *http.Request) {
443444
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
444445

445446
status := map[string]string{}
446-
status["version"] = FactorioServ.Version
447+
status["version"] = FactorioServ.Version.String()
447448
status["base_mod_version"] = FactorioServ.BaseModVersion
448449

449450
resp.Data = status

src/mod_modInfo.go

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ type ModInfoList struct {
1818
Destination string `json:"-"`
1919
}
2020
type ModInfo struct {
21-
Name string `json:"name"`
22-
Version string `json:"version"`
23-
Title string `json:"title"`
24-
Author string `json:"author"`
25-
FileName string `json:"file_name"`
26-
FactorioVersion string `json:"factorio_version"`
27-
Dependencies []string `json:"dependencies"`
28-
Compatibility bool `json:"compatibility"`
21+
Name string `json:"name"`
22+
Version string `json:"version"`
23+
Title string `json:"title"`
24+
Author string `json:"author"`
25+
FileName string `json:"file_name"`
26+
FactorioVersion Version `json:"factorio_version"`
27+
Dependencies []string `json:"dependencies"`
28+
Compatibility bool `json:"compatibility"`
2929
}
3030

3131
func newModInfoList(destination string) (ModInfoList, error) {
@@ -74,33 +74,37 @@ func (modInfoList *ModInfoList) listInstalledMods() error {
7474

7575
modInfo.FileName = info.Name()
7676

77-
var baseDependency string
78-
for _, dependency := range modInfo.Dependencies {
79-
if strings.HasPrefix(dependency, "base") {
80-
splittedDep := strings.Split(dependency, "=")
77+
var base Version
78+
for _, dep := range modInfo.Dependencies {
79+
dep = strings.TrimSpace(dep)
80+
if dep == "" {
81+
continue
82+
}
8183

82-
if len(splittedDep) == 1 {
83-
log.Printf("basemod without version specified!")
84-
break
85-
}
84+
parts := strings.Split(dep, " ")
85+
if len(parts) != 3 {
86+
log.Printf("skipping dependency '%s' in '%s': invalid format\n", dep, modInfo.Name)
87+
}
88+
if parts[0] != "base" {
89+
continue
90+
}
8691

87-
baseDependency = strings.Split(dependency, "=")[1]
88-
break
92+
if parts[1] != ">=" {
93+
log.Printf("skipping dependency '%s' in '%s': unsupported comparison\n", dep, modInfo.Name)
8994
}
90-
}
91-
if baseDependency != "" {
92-
modInfo.Compatibility, err = checkModCompatibility(baseDependency)
93-
if err != nil {
94-
log.Printf("error checking mod compatibility: %s", err)
95-
return err
95+
96+
if err := base.UnmarshalText([]byte(parts[2])); err != nil {
97+
log.Printf("skipping dependency '%s' in '%s': %v\n", dep, modInfo.Name, err)
9698
}
99+
100+
break
101+
}
102+
103+
if !base.Equals(NilVersion) {
104+
modInfo.Compatibility = !FactorioServ.Version.Less(base)
97105
} else {
98106
log.Println("error finding basemodDependency. Using FactorioVersion...")
99-
modInfo.Compatibility, err = checkModCompatibility(modInfo.FactorioVersion + ".0")
100-
if err != nil {
101-
log.Printf("error checking Compatibility with FactorioVersion: %s", err)
102-
return err
103-
}
107+
modInfo.Compatibility = !FactorioServ.Version.Less(modInfo.FactorioVersion)
104108
}
105109

106110
modInfoList.Mods = append(modInfoList.Mods, modInfo)

src/mods.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"os"
1313
"path/filepath"
1414
"strings"
15-
"github.com/Masterminds/semver"
1615
)
1716

1817
type LoginErrorResponse struct {
@@ -345,19 +344,3 @@ func modStartUp() {
345344
}
346345
}
347346
}
348-
349-
func checkModCompatibility(modVersion string) (compatible bool, err error) {
350-
compatible = false
351-
modVersion = strings.TrimSpace(modVersion)
352-
if !strings.HasPrefix(modVersion, "~") {
353-
modVersion = "~" + modVersion
354-
}
355-
356-
constraint, err := semver.NewConstraint(modVersion)
357-
if err != nil {
358-
log.Printf("error loading constraint: %s", err)
359-
return
360-
}
361-
362-
return constraint.Check(FactorioServ.SemVerVersion), nil
363-
}

src/version.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
)
8+
9+
var NilVersion = Version{0, 0, 0}
10+
11+
// Version represents a semantic version
12+
type Version [3]uint
13+
14+
func (v Version) String() string {
15+
return fmt.Sprintf("%d.%d.%d", v[0], v[1], v[2])
16+
}
17+
18+
// MarshalText implements encoding.TextMarshaller for Version
19+
func (v Version) MarshalText() (text []byte, err error) {
20+
return []byte(v.String()), nil
21+
}
22+
23+
// UnmarshalText implements encoding.TextUnmarshaller for Version
24+
func (v *Version) UnmarshalText(text []byte) error {
25+
parts := strings.SplitN(string(text), ".", 3)
26+
for i, part := range parts {
27+
p, err := strconv.ParseUint(part, 10, 32)
28+
if err != nil {
29+
return err
30+
}
31+
v[i] = uint(p)
32+
}
33+
return nil
34+
}
35+
36+
// Equals returns true if both version are equal
37+
func (v Version) Equals(b Version) bool {
38+
return v[0] == b[0] && v[1] == b[1] && v[2] == b[2]
39+
}
40+
41+
// Less returns true if the receiver version is less than the argument version
42+
func (v Version) Less(b Version) bool {
43+
switch {
44+
case v[0] < b[0]:
45+
return true
46+
case v[0] == b[0] && v[1] < b[1]:
47+
return true
48+
case v[0] == b[0] && v[1] == b[1] && v[2] < b[2]:
49+
return true
50+
default:
51+
return false
52+
}
53+
}

0 commit comments

Comments
 (0)