feat: vanilla toggle per install (#13)

* feat: vanilla toggle per install

* fix: update set-vanilla cmd description

* fix: use viper for the set-vanilla off flag

* fix: writing lockfile when the directory didn't exist

* fix: check for nil selected install in header vanilla message

---------

Co-authored-by: Vilsol <me@vil.so>
This commit is contained in:
mircearoata 2023-12-06 05:02:06 +01:00 committed by GitHub
parent 4e1993fe25
commit ea983cf851
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 116 additions and 20 deletions

View file

@ -37,6 +37,7 @@ type Installation struct {
DiskInstance disk.Disk `json:"-"` DiskInstance disk.Disk `json:"-"`
Path string `json:"path"` Path string `json:"path"`
Profile string `json:"profile"` Profile string `json:"profile"`
Vanilla bool `json:"vanilla"`
} }
func InitInstallations() (*Installations, error) { func InitInstallations() (*Installations, error) {
@ -127,6 +128,7 @@ func (i *Installations) AddInstallation(ctx *GlobalContext, installPath string,
installation := &Installation{ installation := &Installation{
Path: absolutePath, Path: absolutePath,
Profile: profile, Profile: profile,
Vanilla: false,
} }
if err := installation.Validate(ctx); err != nil { if err := installation.Validate(ctx); err != nil {
@ -285,16 +287,23 @@ func (i *Installation) WriteLockFile(ctx *GlobalContext, lockfile LockFile) erro
return err return err
} }
marshaledLockfile, err := json.MarshalIndent(lockfile, "", " ")
if err != nil {
return errors.Wrap(err, "failed to serialize lockfile json")
}
d, err := i.GetDisk() d, err := i.GetDisk()
if err != nil { if err != nil {
return err return err
} }
lockfileDir := filepath.Dir(lockfilePath)
if err := d.Exists(lockfileDir); d.IsNotExist(err) {
if err := d.MkDir(lockfileDir); err != nil {
return errors.Wrap(err, "failed creating lockfile directory")
}
}
marshaledLockfile, err := json.MarshalIndent(lockfile, "", " ")
if err != nil {
return errors.Wrap(err, "failed to serialize lockfile json")
}
if err := d.Write(lockfilePath, marshaledLockfile); err != nil { if err := d.Write(lockfilePath, marshaledLockfile); err != nil {
return errors.Wrap(err, "failed writing lockfile") return errors.Wrap(err, "failed writing lockfile")
} }
@ -302,6 +311,31 @@ func (i *Installation) WriteLockFile(ctx *GlobalContext, lockfile LockFile) erro
return nil return nil
} }
func (i *Installation) ResolveProfile(ctx *GlobalContext) (LockFile, error) {
lockFile, err := i.LockFile(ctx)
if err != nil {
return nil, err
}
resolver := NewDependencyResolver(ctx.APIClient)
gameVersion, err := i.GetGameVersion(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to detect game version")
}
lockfile, err := ctx.Profiles.Profiles[i.Profile].Resolve(resolver, lockFile, gameVersion)
if err != nil {
return nil, errors.Wrap(err, "could not resolve mods")
}
if err := i.WriteLockFile(ctx, lockfile); err != nil {
return nil, errors.Wrap(err, "failed to write lockfile")
}
return lockfile, nil
}
type InstallUpdate struct { type InstallUpdate struct {
ModName string ModName string
OverallProgress float64 OverallProgress float64
@ -314,21 +348,14 @@ func (i *Installation) Install(ctx *GlobalContext, updates chan InstallUpdate) e
return errors.Wrap(err, "failed to validate installation") return errors.Wrap(err, "failed to validate installation")
} }
lockFile, err := i.LockFile(ctx) lockfile := make(LockFile)
if err != nil {
return err
}
resolver := NewDependencyResolver(ctx.APIClient) if !i.Vanilla {
var err error
gameVersion, err := i.GetGameVersion(ctx) lockfile, err = i.ResolveProfile(ctx)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to detect game version") return errors.Wrap(err, "failed to resolve lockfile")
} }
lockfile, err := ctx.Profiles.Profiles[i.Profile].Resolve(resolver, lockFile, gameVersion)
if err != nil {
return errors.Wrap(err, "could not resolve mods")
} }
d, err := i.GetDisk() d, err := i.GetDisk()
@ -435,7 +462,7 @@ func (i *Installation) Install(ctx *GlobalContext, updates chan InstallUpdate) e
completed++ completed++
} }
return i.WriteLockFile(ctx, lockfile) return nil
} }
func (i *Installation) SetProfile(ctx *GlobalContext, profile string) error { func (i *Installation) SetProfile(ctx *GlobalContext, profile string) error {

View file

@ -37,5 +37,9 @@ func TestAddInstallation(t *testing.T) {
err = installation.Install(ctx, nil) err = installation.Install(ctx, nil)
testza.AssertNoError(t, err) testza.AssertNoError(t, err)
installation.Vanilla = true
err = installation.Install(ctx, nil)
testza.AssertNoError(t, err)
} }
} }

View file

@ -0,0 +1,46 @@
package installation
import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/satisfactorymodding/ficsit-cli/cli"
)
func init() {
setVanillaCmd.Flags().BoolP("off", "o", false, "Disable vanilla")
Cmd.AddCommand(setVanillaCmd)
}
var setVanillaCmd = &cobra.Command{
Use: "set-vanilla <path>",
Short: "Set the installation to vanilla mode or not",
Args: cobra.ExactArgs(1),
PreRun: func(cmd *cobra.Command, args []string) {
_ = viper.BindPFlag("off", cmd.Flags().Lookup("off"))
},
RunE: func(cmd *cobra.Command, args []string) error {
global, err := cli.InitCLI(false)
if err != nil {
return err
}
var installation *cli.Installation
for _, install := range global.Installations.Installations {
if install.Path == args[0] {
installation = install
break
}
}
if installation == nil {
return errors.New("installation not found")
}
installation.Vanilla = !viper.GetBool("off")
return global.Save()
},
}

View file

@ -44,6 +44,18 @@ func (h headerComponent) View() string {
} else { } else {
out += "None" out += "None"
} }
out += "\n"
out += h.labelStyle.Render("Vanilla: ")
if h.root.GetCurrentInstallation() != nil {
if h.root.GetCurrentInstallation().Vanilla {
out += "On"
} else {
out += "Off"
}
} else {
out += "N/A"
}
return lipgloss.NewStyle().Margin(1, 0).Render(out) return lipgloss.NewStyle().Margin(1, 0).Render(out)
} }

View file

@ -73,6 +73,13 @@ func NewMainMenu(root components.RootModel) tea.Model {
return newModel, newModel.Init() return newModel, newModel.Init()
}, },
}, },
utils.SimpleItem[mainMenu]{
ItemTitle: "Toggle Vanilla",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {
currentModel.root.GetCurrentInstallation().Vanilla = !currentModel.root.GetCurrentInstallation().Vanilla
return currentModel, nil
},
},
utils.SimpleItem[mainMenu]{ utils.SimpleItem[mainMenu]{
ItemTitle: "Profiles", ItemTitle: "Profiles",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {