mirror of
https://github.com/packwiz/packwiz.git
synced 2025-04-19 21:16:30 +02:00
Redo update system to work with batched updates
This commit is contained in:
parent
adcde05693
commit
b77e2080c7
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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!!
|
||||
|
20
core/mod.go
20
core/mod.go
@ -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
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ func init() {
|
||||
},
|
||||
}},
|
||||
})
|
||||
core.UpdateParsers["curseforge"] = cfUpdateParser{}
|
||||
core.Updaters["curseforge"] = cfUpdater{}
|
||||
}
|
||||
|
||||
var fileIDRegexes = [...]*regexp.Regexp{
|
||||
@ -100,7 +100,7 @@ func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo, inde
|
||||
updateMap := make(map[string]map[string]interface{})
|
||||
var err error
|
||||
|
||||
updateMap["curseforge"], err = cfUpdater{
|
||||
updateMap["curseforge"], err = cfUpdateData{
|
||||
ProjectID: modInfo.ID,
|
||||
FileID: fileInfo.ID,
|
||||
// TODO: determine update channel
|
||||
@ -162,11 +162,11 @@ func cmdDoc(flags core.Flags, mod string) error {
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
}
|
||||
updateData, ok := modData.GetParsedUpdater("curseforge")
|
||||
updateData, ok := modData.GetParsedUpdateData("curseforge")
|
||||
if !ok {
|
||||
return cli.NewExitError("This mod doesn't seem to be a curseforge mod!", 1)
|
||||
}
|
||||
cfUpdateData := updateData.(cfUpdater)
|
||||
cfUpdateData := updateData.(cfUpdateData)
|
||||
fmt.Println("Opening browser...")
|
||||
url := "https://minecraft.curseforge.com/projects/" + strconv.Itoa(cfUpdateData.ProjectID)
|
||||
err = open.Start(url)
|
||||
@ -178,32 +178,36 @@ func cmdDoc(flags core.Flags, mod string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type cfUpdateParser struct{}
|
||||
|
||||
func (u cfUpdateParser) ParseUpdate(updateUnparsed map[string]interface{}) (core.Updater, error) {
|
||||
var updater cfUpdater
|
||||
err := mapstructure.Decode(updateUnparsed, &updater)
|
||||
return updater, err
|
||||
}
|
||||
|
||||
type cfUpdater struct {
|
||||
type cfUpdateData struct {
|
||||
ProjectID int `mapstructure:"project-id"`
|
||||
FileID int `mapstructure:"file-id"`
|
||||
ReleaseChannel string `mapstructure:"release-channel"`
|
||||
}
|
||||
|
||||
func (u cfUpdater) DoUpdate(mod core.Mod) (bool, error) {
|
||||
func (u cfUpdateData) ToMap() (map[string]interface{}, error) {
|
||||
newMap := make(map[string]interface{})
|
||||
err := mapstructure.Decode(u, &newMap)
|
||||
return newMap, err
|
||||
}
|
||||
|
||||
type cfUpdater struct{}
|
||||
|
||||
func (u cfUpdater) ParseUpdate(updateUnparsed map[string]interface{}) (interface{}, error) {
|
||||
var updateData cfUpdateData
|
||||
err := mapstructure.Decode(updateUnparsed, &updateData)
|
||||
return updateData, err
|
||||
}
|
||||
|
||||
func (u cfUpdater) CheckUpdate(mod []core.Mod) ([]core.UpdateCheck, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (u cfUpdater) DoUpdate(mod []*core.Mod, cachedState []interface{}) error {
|
||||
// TODO: implement updating
|
||||
// modInfoData, err := getModInfo(u.ProjectID)
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (u cfUpdater) ToMap() (map[string]interface{}, error) {
|
||||
newMap := make(map[string]interface{})
|
||||
err := mapstructure.Decode(u, &newMap)
|
||||
return newMap, err
|
||||
return nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user