Switch to cobra/viper

This commit is contained in:
comp500
2019-09-16 21:44:40 +01:00
parent 8915e16614
commit 4fea7ceebf
17 changed files with 985 additions and 719 deletions

View File

@@ -10,7 +10,7 @@ import (
"github.com/agnivade/levenshtein"
"github.com/comp500/packwiz/core"
"github.com/urfave/cli"
"github.com/spf13/cobra"
"gopkg.in/dixonwille/wmenu.v4"
)
@@ -21,255 +21,279 @@ type installableDep struct {
fileInfo modFileInfo
}
func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error {
if len(mod) == 0 {
return cli.NewExitError("You must specify a mod.", 1)
}
pack, err := core.LoadPack(flags)
if err != nil {
return cli.NewExitError(err, 1)
}
index, err := pack.LoadIndex()
if err != nil {
return cli.NewExitError(err, 1)
}
mcVersion, err := pack.GetMCVersion()
if err != nil {
return cli.NewExitError(err, 1)
}
var done bool
var modID, fileID int
// If modArgsTail has anything, go straight to searching - URLs/Slugs should not have spaces!
if len(modArgsTail) == 0 {
done, modID, fileID, err = getFileIDsFromString(mod)
// installCmd represents the install command
var installCmd = &cobra.Command{
Use: "install",
Short: "Install a mod from a curseforge URL, slug or ID",
Aliases: []string{"add", "get"},
Args: cobra.ArbitraryArgs,
Run: func(cmd *cobra.Command, args []string) {
if len(args[0]) == 0 {
fmt.Println("You must specify a mod.")
os.Exit(1)
}
pack, err := core.LoadPack()
if err != nil {
return cli.NewExitError(err, 1)
fmt.Println(err)
os.Exit(1)
}
if !done {
done, modID, err = getModIDFromString(mod)
// Ignore error, go to search instead (e.g. lowercase to search instead of as a slug)
if err != nil {
done = false
}
}
}
modInfoObtained := false
var modInfoData modInfo
if !done {
fmt.Println("Searching CurseForge...")
modArgs := append([]string{mod}, modArgsTail...)
searchTerm := strings.Join(modArgs, " ")
results, err := getSearch(searchTerm, mcVersion)
index, err := pack.LoadIndex()
if err != nil {
return cli.NewExitError(err, 1)
fmt.Println(err)
os.Exit(1)
}
mcVersion, err := pack.GetMCVersion()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if len(results) == 0 {
return cli.NewExitError("No mods found!", 1)
} else if len(results) == 1 {
modInfoData = results[0]
modID = modInfoData.ID
modInfoObtained = true
done = true
} else {
// Find the closest value to the search term
sort.Slice(results, func(i, j int) bool {
return levenshtein.ComputeDistance(searchTerm, results[i].Name) < levenshtein.ComputeDistance(searchTerm, results[j].Name)
})
menu := wmenu.NewMenu("Choose a number:")
for i, v := range results {
menu.Option(v.Name, v, i == 0, nil)
}
menu.Option("Cancel", nil, false, nil)
menu.Action(func(menuRes []wmenu.Opt) error {
if len(menuRes) != 1 || menuRes[0].Value == nil {
fmt.Println("Cancelled!")
return nil
}
// Why is variable shadowing a thing!!!!
var ok bool
modInfoData, ok = menuRes[0].Value.(modInfo)
if !ok {
return cli.NewExitError("Error converting interface from wmenu", 1)
}
modID = modInfoData.ID
modInfoObtained = true
done = true
return nil
})
err = menu.Run()
var done bool
var modID, fileID int
// If there are more than 1 argument, go straight to searching - URLs/Slugs should not have spaces!
if len(args) == 1 {
done, modID, fileID, err = getFileIDsFromString(args[0])
if err != nil {
return cli.NewExitError(err, 1)
fmt.Println(err)
os.Exit(1)
}
if !done {
return nil
done, modID, err = getModIDFromString(args[0])
// Ignore error, go to search instead (e.g. lowercase to search instead of as a slug)
if err != nil {
done = false
}
}
}
}
if !done {
if err == nil {
return cli.NewExitError("No mods found!", 1)
modInfoObtained := false
var modInfoData modInfo
if !done {
fmt.Println("Searching CurseForge...")
searchTerm := strings.Join(args, " ")
results, err := getSearch(searchTerm, mcVersion)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if len(results) == 0 {
fmt.Println("No mods found!")
os.Exit(1)
} else if len(results) == 1 {
modInfoData = results[0]
modID = modInfoData.ID
modInfoObtained = true
done = true
} else {
// Find the closest value to the search term
sort.Slice(results, func(i, j int) bool {
return levenshtein.ComputeDistance(searchTerm, results[i].Name) < levenshtein.ComputeDistance(searchTerm, results[j].Name)
})
menu := wmenu.NewMenu("Choose a number:")
for i, v := range results {
menu.Option(v.Name, v, i == 0, nil)
}
menu.Option("Cancel", nil, false, nil)
menu.Action(func(menuRes []wmenu.Opt) error {
if len(menuRes) != 1 || menuRes[0].Value == nil {
fmt.Println("Cancelled!")
return nil
}
// Why is variable shadowing a thing!!!!
var ok bool
modInfoData, ok = menuRes[0].Value.(modInfo)
if !ok {
fmt.Println("Error converting interface from wmenu")
os.Exit(1)
}
modID = modInfoData.ID
modInfoObtained = true
done = true
return nil
})
err = menu.Run()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if !done {
return
}
}
}
return cli.NewExitError(err, 1)
}
if !modInfoObtained {
modInfoData, err = getModInfo(modID)
if !done {
if err == nil {
fmt.Println("No mods found!")
os.Exit(1)
}
fmt.Println(err)
os.Exit(1)
}
if !modInfoObtained {
modInfoData, err = getModInfo(modID)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
var fileInfoData modFileInfo
fileInfoData, err = getLatestFile(modInfoData, mcVersion, fileID)
if err != nil {
return cli.NewExitError(err, 1)
fmt.Println(err)
os.Exit(1)
}
}
var fileInfoData modFileInfo
fileInfoData, err = getLatestFile(modInfoData, mcVersion, fileID)
if err != nil {
return cli.NewExitError(err, 1)
}
if len(fileInfoData.Dependencies) > 0 {
var depsInstallable []installableDep
var depIDPendingQueue []int
for _, dep := range fileInfoData.Dependencies {
if dep.Type == dependencyTypeRequired {
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
if len(fileInfoData.Dependencies) > 0 {
var depsInstallable []installableDep
var depIDPendingQueue []int
for _, dep := range fileInfoData.Dependencies {
if dep.Type == dependencyTypeRequired {
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
}
}
}
if len(depIDPendingQueue) > 0 {
fmt.Println("Finding dependencies...")
if len(depIDPendingQueue) > 0 {
fmt.Println("Finding dependencies...")
cycles := 0
var installedIDList []int
for len(depIDPendingQueue) > 0 && cycles < maxCycles {
if installedIDList == nil {
// Get modids of all mods
for _, modPath := range index.GetAllMods() {
mod, err := core.LoadMod(modPath)
if err == nil {
data, ok := mod.GetParsedUpdateData("curseforge")
if ok {
updateData, ok := data.(cfUpdateData)
cycles := 0
var installedIDList []int
for len(depIDPendingQueue) > 0 && cycles < maxCycles {
if installedIDList == nil {
// Get modids of all mods
for _, modPath := range index.GetAllMods() {
mod, err := core.LoadMod(modPath)
if err == nil {
data, ok := mod.GetParsedUpdateData("curseforge")
if ok {
if updateData.ProjectID > 0 {
installedIDList = append(installedIDList, updateData.ProjectID)
updateData, ok := data.(cfUpdateData)
if ok {
if updateData.ProjectID > 0 {
installedIDList = append(installedIDList, updateData.ProjectID)
}
}
}
}
}
}
}
// Remove installed IDs from dep queue
i := 0
for _, id := range depIDPendingQueue {
contains := false
for _, id2 := range installedIDList {
if id == id2 {
contains = true
break
// Remove installed IDs from dep queue
i := 0
for _, id := range depIDPendingQueue {
contains := false
for _, id2 := range installedIDList {
if id == id2 {
contains = true
break
}
}
for _, data := range depsInstallable {
if id == data.ID {
contains = true
break
}
}
if !contains {
depIDPendingQueue[i] = id
i++
}
}
for _, data := range depsInstallable {
if id == data.ID {
contains = true
break
}
}
if !contains {
depIDPendingQueue[i] = id
i++
}
}
depIDPendingQueue = depIDPendingQueue[:i]
depIDPendingQueue = depIDPendingQueue[:i]
depInfoData, err := getModInfoMultiple(depIDPendingQueue)
if err != nil {
fmt.Printf("Error retrieving dependency data: %s\n", err.Error())
}
depIDPendingQueue = depIDPendingQueue[:0]
for _, currData := range depInfoData {
depFileInfo, err := getLatestFile(currData, mcVersion, 0)
depInfoData, err := getModInfoMultiple(depIDPendingQueue)
if err != nil {
fmt.Printf("Error retrieving dependency data: %s\n", err.Error())
}
depIDPendingQueue = depIDPendingQueue[:0]
for _, dep := range depFileInfo.Dependencies {
if dep.Type == dependencyTypeRequired {
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
}
}
depsInstallable = append(depsInstallable, installableDep{
currData, depFileInfo,
})
}
cycles++
}
if cycles >= maxCycles {
return cli.NewExitError("Dependencies recurse too deeply! Try increasing maxCycles.", 1)
}
if len(depsInstallable) > 0 {
fmt.Println("Dependencies found:")
for _, v := range depsInstallable {
fmt.Println(v.Name)
}
fmt.Print("Would you like to install them? [Y/n]: ")
answer, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
return cli.NewExitError(err, 1)
}
ansNormal := strings.ToLower(strings.TrimSpace(answer))
if !(len(ansNormal) > 0 && ansNormal[0] == 'n') {
for _, v := range depsInstallable {
err = createModFile(flags, v.modInfo, v.fileInfo, &index)
for _, currData := range depInfoData {
depFileInfo, err := getLatestFile(currData, mcVersion, 0)
if err != nil {
return cli.NewExitError(err, 1)
fmt.Printf("Error retrieving dependency data: %s\n", err.Error())
}
fmt.Printf("Dependency \"%s\" successfully installed! (%s)\n", v.modInfo.Name, v.fileInfo.FileName)
for _, dep := range depFileInfo.Dependencies {
if dep.Type == dependencyTypeRequired {
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
}
}
depsInstallable = append(depsInstallable, installableDep{
currData, depFileInfo,
})
}
cycles++
}
if cycles >= maxCycles {
fmt.Println("Dependencies recurse too deeply! Try increasing maxCycles.")
os.Exit(1)
}
if len(depsInstallable) > 0 {
fmt.Println("Dependencies found:")
for _, v := range depsInstallable {
fmt.Println(v.Name)
}
fmt.Print("Would you like to install them? [Y/n]: ")
answer, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
fmt.Println(err)
os.Exit(1)
}
ansNormal := strings.ToLower(strings.TrimSpace(answer))
if !(len(ansNormal) > 0 && ansNormal[0] == 'n') {
for _, v := range depsInstallable {
err = createModFile(v.modInfo, v.fileInfo, &index)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Dependency \"%s\" successfully installed! (%s)\n", v.modInfo.Name, v.fileInfo.FileName)
}
}
} else {
fmt.Println("All dependencies are already installed!")
}
} else {
fmt.Println("All dependencies are already installed!")
}
}
}
err = createModFile(flags, modInfoData, fileInfoData, &index)
if err != nil {
return cli.NewExitError(err, 1)
}
err = createModFile(modInfoData, fileInfoData, &index)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = index.Write()
if err != nil {
return cli.NewExitError(err, 1)
}
err = pack.UpdateIndexHash()
if err != nil {
return cli.NewExitError(err, 1)
}
err = pack.Write()
if err != nil {
return cli.NewExitError(err, 1)
}
err = index.Write()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = pack.UpdateIndexHash()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = pack.Write()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Mod \"%s\" successfully installed! (%s)\n", modInfoData.Name, fileInfoData.FileName)
return nil
fmt.Printf("Mod \"%s\" successfully installed! (%s)\n", modInfoData.Name, fileInfoData.FileName)
},
}
func getLatestFile(modInfoData modInfo, mcVersion string, fileID int) (modFileInfo, error) {
@@ -300,3 +324,7 @@ func getLatestFile(modInfoData modInfo, mcVersion string, fileID int) (modFileIn
}
return fileInfoData, nil
}
func init() {
curseforgeCmd.AddCommand(installCmd)
}