diff --git a/README.md b/README.md
index 70b62f9..eb3ca0f 100644
--- a/README.md
+++ b/README.md
@@ -4,58 +4,58 @@ A CLI tool for managing mods for the game Satisfactory
## Installation
-### Windows
+
-Download the appropriate `.exe` for your CPU architecture.
-
-* [AMD64 (64-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_windows_amd64.exe)
-* [386 (32-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_windows_386.exe)
-* [ARM64 (64-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_windows_arm64.exe)
-* [ARMv7 (32-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_windows_armv7.exe)
-
-### Linux
-
-#### Arch
-
-A package is published to AUR under the name [`ficsit-cli-bin`](https://aur.archlinux.org/packages/ficsit-cli-bin)
-
-```shell
-yay -S ficsit-cli-bin
-```
-
-#### Debian (inc. Ubuntu, Mint, PopOS!, etc)
-
-Download the appropriate `.deb` for your CPU architecture.
-
-* [AMD64 (64-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_amd64.deb)
-* [386 (32-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_386.deb)
-* [ARM64 (64-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_arm64.deb)
-* [ARMv7 (32-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_armv7.deb)
-* [PowerPC64](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_ppc64le.deb)
-
-#### Fedora
-
-Download the appropriate `.rpm` for your CPU architecture.
-
-* [AMD64 (64-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_amd64.rpm)
-* [386 (32-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_386.rpm)
-* [ARM64 (64-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_arm64.rpm)
-* [ARMv7 (32-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_armv7.rpm)
-* [PowerPC64](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_ppc64le.rpm)
-
-#### Alpine
-
-Download the appropriate `.apk` for your CPU architecture.
-
-* [AMD64 (64-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_amd64.apk)
-* [386 (32-bit)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_386.apk)
-* [ARM64 (64-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_arm64.apk)
-* [ARMv7 (32-bit ARM)](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_armv7.apk)
-* [PowerPC64](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_linux_ppc64le.apk)
-
-### macOS
-
-Download the "all" build [here](https://github.com/Vilsol/ficsit-cli/releases/latest/download/ficsit_darwin_all).
## Usage
diff --git a/cli/context.go b/cli/context.go
index 7352f8c..0bf1ed7 100644
--- a/cli/context.go
+++ b/cli/context.go
@@ -64,6 +64,29 @@ func InitCLI(apiOnly bool) (*GlobalContext, error) {
return globalContext, nil
}
+// Wipe will remove any trace of ficsit anywhere
+func (g *GlobalContext) Wipe() error {
+ // Wipe all installations
+ for _, installation := range g.Installations.Installations {
+ if err := installation.Wipe(); err != nil {
+ return errors.Wrap(err, "failed wiping installation")
+ }
+
+ if err := g.Installations.DeleteInstallation(installation.Path); err != nil {
+ return errors.Wrap(err, "failed deleting installation")
+ }
+ }
+
+ // Wipe all profiles
+ for _, profile := range g.Profiles.Profiles {
+ if err := g.Profiles.DeleteProfile(profile.Name); err != nil {
+ return errors.Wrap(err, "failed deleting profile")
+ }
+ }
+
+ return g.Save()
+}
+
func (g *GlobalContext) Save() error {
if err := g.Installations.Save(); err != nil {
return errors.Wrap(err, "failed to save installations")
diff --git a/cli/disk/main.go b/cli/disk/main.go
index c438352..018a2ae 100644
--- a/cli/disk/main.go
+++ b/cli/disk/main.go
@@ -9,14 +9,35 @@ import (
)
type Disk interface {
+ // Exists checks if the provided file or directory exists
Exists(path string) error
+
+ // Read returns the entire file as a byte buffer
+ //
+ // Returns error if provided path is not a file
Read(path string) ([]byte, error)
+
+ // Write writes provided byte buffer to the path
Write(path string, data []byte) error
+
+ // Remove deletes the provided file or directory recursively
Remove(path string) error
+
+ // MkDir creates the provided directory recursively
MkDir(path string) error
+
+ // ReadDir returns all entries within the directory
+ //
+ // Returns error if provided path is not a directory
ReadDir(path string) ([]Entry, error)
+
+ // IsNotExist returns true if provided error is a not-exist type error
IsNotExist(err error) bool
+
+ // IsExist returns true if provided error is a does-exist type error
IsExist(err error) bool
+
+ // Open opens provided path for writing
Open(path string, flag int) (io.WriteCloser, error)
}
diff --git a/cli/installations.go b/cli/installations.go
index 101f9b5..403beb3 100644
--- a/cli/installations.go
+++ b/cli/installations.go
@@ -312,6 +312,20 @@ func (i *Installation) WriteLockFile(ctx *GlobalContext, lockfile LockFile) erro
return nil
}
+func (i *Installation) Wipe() error {
+ d, err := i.GetDisk()
+ if err != nil {
+ return err
+ }
+
+ modsDirectory := filepath.Join(i.BasePath(), "FactoryGame", "Mods")
+ if err := d.Remove(modsDirectory); err != nil {
+ return errors.Wrap(err, "failed removing Mods directory")
+ }
+
+ return nil
+}
+
func (i *Installation) ResolveProfile(ctx *GlobalContext) (LockFile, error) {
lockFile, err := i.LockFile(ctx)
if err != nil {
diff --git a/cli/resolving_test.go b/cli/resolving_test.go
index 8060621..ad586a9 100644
--- a/cli/resolving_test.go
+++ b/cli/resolving_test.go
@@ -2,6 +2,7 @@ package cli
import (
"math"
+ "os"
"testing"
"github.com/MarvinJWendt/testza"
@@ -69,3 +70,63 @@ func TestResolutionNonExistentMod(t *testing.T) {
testza.AssertEqual(t, "failed resolving profile dependencies: failed to solve dependencies: failed to make decision: failed to get package versions: mod ThisModDoesNotExist$$$ not found", err.Error())
}
+
+func TestUpdateMods(t *testing.T) {
+ ctx, err := InitCLI(false)
+ testza.AssertNoError(t, err)
+
+ err = ctx.Wipe()
+ testza.AssertNoError(t, err)
+
+ resolver := NewDependencyResolver(ctx.Provider)
+
+ oldLockfile, err := (&Profile{
+ Name: DefaultProfileName,
+ Mods: map[string]ProfileMod{
+ "AreaActions": {
+ Version: "1.6.5",
+ Enabled: true,
+ },
+ },
+ }).Resolve(resolver, nil, math.MaxInt)
+
+ testza.AssertNoError(t, err)
+ testza.AssertNotNil(t, oldLockfile)
+ testza.AssertLen(t, oldLockfile, 2)
+
+ profileName := "UpdateTest"
+ profile, err := ctx.Profiles.AddProfile(profileName)
+ testza.AssertNoError(t, err)
+ testza.AssertNoError(t, profile.AddMod("AreaActions", "<=1.6.6"))
+
+ serverLocation := os.Getenv("SF_DEDICATED_SERVER")
+ if serverLocation != "" {
+ installation, err := ctx.Installations.AddInstallation(ctx, serverLocation, profileName)
+ testza.AssertNoError(t, err)
+ testza.AssertNotNil(t, installation)
+
+ err = installation.WriteLockFile(ctx, oldLockfile)
+ testza.AssertNoError(t, err)
+
+ err = installation.Install(ctx, nil)
+ testza.AssertNoError(t, err)
+
+ lockFile, err := installation.LockFile(ctx)
+ testza.AssertNoError(t, err)
+
+ testza.AssertEqual(t, 2, len(*lockFile))
+ testza.AssertEqual(t, "1.6.5", (*lockFile)["AreaActions"].Version)
+
+ err = installation.UpdateMods(ctx, []string{"AreaActions"})
+ testza.AssertNoError(t, err)
+
+ lockFile, err = installation.LockFile(ctx)
+ testza.AssertNoError(t, err)
+
+ testza.AssertEqual(t, 2, len(*lockFile))
+ testza.AssertEqual(t, "1.6.6", (*lockFile)["AreaActions"].Version)
+
+ err = installation.Install(ctx, nil)
+ testza.AssertNoError(t, err)
+ }
+}