Redo update system to work with batched updates

This commit is contained in:
comp500
2019-06-16 14:25:54 +01:00
parent adcde05693
commit b77e2080c7
4 changed files with 76 additions and 44 deletions

View File

@@ -7,8 +7,8 @@ import (
"os"
"path/filepath"
"sort"
"time"
"strings"
"time"
"github.com/BurntSushi/toml"
"github.com/vbauerster/mpb/v4"
@@ -192,6 +192,7 @@ func (in *Index) Refresh() error {
}
start := time.Now()
defer func() {
// TODO: this is stupid, traverse the file tree first *then* read all the files
if progressCurrent >= progressLength {
progressLength++
progress.SetTotal(int64(progressLength), false)
@@ -272,7 +273,7 @@ func (in *Index) RefreshFileWithHash(path, format, hash string, mod bool) error
func (in Index) FindMod(modName string) (string, bool) {
for _, v := range in.Files {
if v.MetaFile {
_, file := filepath.Split(v.File);
_, file := filepath.Split(v.File)
fileTrimmed := strings.TrimSuffix(file, ModExtension)
if fileTrimmed == modName {
return v.File, true
@@ -280,4 +281,4 @@ func (in Index) FindMod(modName string) (string, bool) {
}
}
return "", false
}
}

View File

@@ -1,16 +1,43 @@
package core
// UpdateParsers stores all the update parsers that packwiz can use. Add your own update systems to this map.
var UpdateParsers = make(map[string]UpdateParser)
// UpdateParser takes an unparsed interface{} (as a map[string]interface{}), and returns an Updater for a mod file.
// This can be done using the mapstructure library or your own parsing methods.
type UpdateParser interface {
ParseUpdate(map[string]interface{}) (Updater, error)
}
// Updaters stores all the updaters that packwiz can use. Add your own update systems to this map, keyed by the configuration name.
var Updaters = make(map[string]Updater)
// Updater checks for and does updates on a mod
// Updater is used to process updates on mods
type Updater interface {
// DoUpdate returns true if an update was done, false otherwise
DoUpdate(Mod) (bool, error)
// ParseUpdate takes an unparsed interface{} (as a map[string]interface{}), and returns an Updater for a mod file.
// This can be done using the mapstructure library or your own parsing methods.
ParseUpdate(map[string]interface{}) (interface{}, error)
// CheckUpdate checks whether there is an update for each of the mods in the given slice,
// called for all of the mods that this updater handles
CheckUpdate([]Mod) ([]UpdateCheck, error)
// DoUpdate carries out the update previously queried in CheckUpdate, on each Mod's metadata,
// given pointers to Mods and the value of CachedState for each mod
DoUpdate([]*Mod, []interface{}) error
}
// UpdateCheck represents the data returned from CheckUpdate for each mod
type UpdateCheck struct {
// UpdateAvailable is true if an update is available for this mod
UpdateAvailable bool
// UpdateString is a string that details the update in some way to the user. Usually this will be in the form of
// a version change (1.0.0 -> 1.0.1), or a file name change (thanos-skin-1.0.0.jar -> thanos-skin-1.0.1.jar).
UpdateString string
// CachedState can be used to preserve per-mod state between CheckUpdate and DoUpdate (e.g. file metadata)
CachedState interface{}
// Error stores an error for this specific mod
// Errors can also be returned from CheckUpdate directly, if the whole operation failed completely (so only 1 error is printed)
// If an error is returned for a mod, or from CheckUpdate, DoUpdate is not called on that mod / at all
Error error
}
// TODO: new docs
// to carry out updating:
// go through all metafiles in index
// make a []Mod for each updater, so map[string][]Mod
// for each Mod, check the "first" updater, then give the Mod to the map
// go through the map, call CheckUpdate with the []Mod
// print to user, if interactive mode
// call doupdate with the mods and interfaces!!

View File

@@ -19,8 +19,8 @@ type Mod struct {
Optional bool `toml:"optional,omitempty"`
Download ModDownload `toml:"download"`
// Update is a map of map of stuff, so you can store arbitrary values on string keys to define updating
Update map[string]map[string]interface{} `toml:"update"`
updaters map[string]Updater
Update map[string]map[string]interface{} `toml:"update"`
updateData map[string]interface{}
}
// ModDownload specifies how to download the mod file
@@ -43,16 +43,16 @@ func LoadMod(modFile string) (Mod, error) {
if _, err := toml.DecodeFile(modFile, &mod); err != nil {
return Mod{}, err
}
mod.updaters = make(map[string]Updater)
// Horrible reflection library to convert to Updaters
mod.updateData = make(map[string]interface{})
// Horrible reflection library to convert map[string]interface to proper struct
for k, v := range mod.Update {
updateParser, ok := UpdateParsers[k]
updater, ok := Updaters[k]
if ok {
updater, err := updateParser.ParseUpdate(v)
updateData, err := updater.ParseUpdate(v)
if err != nil {
return mod, err
}
mod.updaters[k] = updater
mod.updateData[k] = updateData
} else {
return mod, errors.New("Update plugin " + k + " not found!")
}
@@ -86,8 +86,8 @@ func (m Mod) Write() (string, string, error) {
return "sha256", hashString, err
}
// GetParsedUpdater can be used to retrieve updater-specific information after parsing a mod file
func (m Mod) GetParsedUpdater(updaterName string) (Updater, bool) {
upd, ok := m.updaters[updaterName]
// GetParsedUpdateData can be used to retrieve updater-specific information after parsing a mod file
func (m Mod) GetParsedUpdateData(updaterName string) (interface{}, bool) {
upd, ok := m.updateData[updaterName]
return upd, ok
}