From 0f3096e251e205eb45c84bbd94bb424ac555a3d8 Mon Sep 17 00:00:00 2001 From: comp500 Date: Mon, 16 May 2022 21:06:10 +0100 Subject: [PATCH] Use the correct directories for non-mod files; use .pw.toml extension The mods-folder option is now replaced with two new options: meta-folder and meta-folder-base This allows non-mod files to use the correct directory based on their category; with correct import of resource packs/etc from CurseForge packs, and the ability to override this behaviour. To improve the reliability of packwiz metadata file marking (in the index), new files now use .pw.toml as the extension - any extension can be used, but .pw.toml will now be automatically be marked as a metafile regardless of folder, so you can easily move metadata files around. Existing metadata files will still work (as metafile = true is set in the index); though in the future .pw.toml may be required. --- cmd/root.go | 20 +++++++++++++++++--- core/index.go | 15 ++++----------- core/mod.go | 6 +++--- core/resolve.go | 20 +++----------------- curseforge/curseforge.go | 21 ++++++++++++++++++--- curseforge/import.go | 3 +-- curseforge/request.go | 3 +++ modrinth/install.go | 9 +++++++-- 8 files changed, 56 insertions(+), 41 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 105ff6d..e41c35d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "github.com/packwiz/packwiz/core" + "github.com/spf13/pflag" "os" "path/filepath" @@ -11,7 +12,6 @@ import ( ) var packFile string -var modsFolder string var cfgFile string // rootCmd represents the base command when called without any subcommands @@ -38,8 +38,22 @@ func init() { rootCmd.PersistentFlags().StringVar(&packFile, "pack-file", "pack.toml", "The modpack metadata file to use") _ = viper.BindPFlag("pack-file", rootCmd.PersistentFlags().Lookup("pack-file")) - rootCmd.PersistentFlags().StringVar(&modsFolder, "mods-folder", "mods", "The default folder to store mod metadata files in") - _ = viper.BindPFlag("mods-folder", rootCmd.PersistentFlags().Lookup("mods-folder")) + // Make mods-folder an alias for meta-folder + viper.RegisterAlias("mods-folder", "meta-folder") + rootCmd.SetGlobalNormalizationFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName { + if name == "mods-folder" { + return "meta-folder" + } + return pflag.NormalizedName(name) + }) + + var metaFolder string + rootCmd.PersistentFlags().StringVar(&metaFolder, "meta-folder", "", "The folder in which new metadata files will be added, defaulting to a folder based on the category (mods, resourcepacks, etc; if the category is unknown the current directory is used)") + _ = viper.BindPFlag("meta-folder", rootCmd.PersistentFlags().Lookup("meta-folder")) + + var metaFolderBase string + rootCmd.PersistentFlags().StringVar(&metaFolderBase, "meta-folder-base", ".", "The base folder from which meta-folder will be resolved, defaulting to the current directory (so you can put all mods/etc in a subfolder while still using the default behaviour)") + _ = viper.BindPFlag("meta-folder-base", rootCmd.PersistentFlags().Lookup("meta-folder-base")) file, err := core.GetPackwizLocalStore() if err != nil { diff --git a/core/index.go b/core/index.go index 5777271..3095de3 100644 --- a/core/index.go +++ b/core/index.go @@ -150,16 +150,9 @@ func (in *Index) updateFile(path string) error { } mod := false - // If the file has an extension of toml and is in the mods folder, set mod to true - absFileDir, err := filepath.Abs(filepath.Dir(path)) - if err == nil { - modsDir := filepath.Join(in.GetPackRoot(), viper.GetString("mods-folder")) - absModsDir, err := filepath.Abs(modsDir) - if err == nil { - if absFileDir == absModsDir && strings.HasSuffix(filepath.Base(path), ".toml") { - mod = true - } - } + // If the file has an extension of pw.toml, set mod to true + if strings.HasSuffix(filepath.Base(path), MetaExtension) { + mod = true } return in.updateFileHashGiven(path, "sha256", hashString, mod) @@ -341,7 +334,7 @@ func (in Index) FindMod(modName string) (string, bool) { for _, v := range in.Files { if v.MetaFile { _, file := filepath.Split(v.File) - fileTrimmed := strings.TrimSuffix(file, ModExtension) + fileTrimmed := strings.TrimSuffix(file, MetaExtension) if fileTrimmed == modName { return filepath.Join(filepath.Dir(in.indexFile), filepath.FromSlash(v.File)), true } diff --git a/core/mod.go b/core/mod.go index 9afa4e3..73a0274 100644 --- a/core/mod.go +++ b/core/mod.go @@ -72,9 +72,9 @@ func LoadMod(modFile string) (Mod, error) { return mod, nil } -// SetMetaName sets the mod metadata file from a given file name (to be put in the mods folder) -func (m *Mod) SetMetaName(metaName string, index Index) string { - m.metaFile = ResolveMod(metaName, index) +// SetMetaPath sets the file path of a metadata file +func (m *Mod) SetMetaPath(metaFile string) string { + m.metaFile = metaFile return m.metaFile } diff --git a/core/resolve.go b/core/resolve.go index 571d343..19494f5 100644 --- a/core/resolve.go +++ b/core/resolve.go @@ -1,19 +1,5 @@ package core -import ( - "path/filepath" - "strings" - - "github.com/spf13/viper" -) - -// ModExtension is the file extension of the mod metadata files -const ModExtension = ".toml" - -// ResolveMod returns the path to a mod file from it's name -func ResolveMod(modName string, index Index) string { - // TODO: should this work for any metadata file? - fileName := strings.ToLower(strings.TrimSuffix(modName, ModExtension)) + ModExtension - modsDir := filepath.Join(index.GetPackRoot(), viper.GetString("mods-folder")) - return filepath.Join(modsDir, fileName) -} +// MetaExtension is the file extension of the mod metadata files +// Note that this is currently not required; it will only be used for new files. +const MetaExtension = ".pw.toml" diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go index 4843275..7972fef 100644 --- a/curseforge/curseforge.go +++ b/curseforge/curseforge.go @@ -4,6 +4,7 @@ import ( "errors" "github.com/spf13/viper" "golang.org/x/exp/slices" + "path/filepath" "regexp" "strconv" "strings" @@ -136,8 +137,7 @@ func parseSlugOrUrl(url string) (game string, category string, slug string, file return } -// TODO: put projects into folders based on these -var defaultFolders = map[int]map[int]string{ +var defaultFolders = map[uint32]map[uint32]string{ 432: { // Minecraft 5: "plugins", // Bukkit Plugins 12: "resourcepacks", @@ -146,6 +146,21 @@ var defaultFolders = map[int]map[int]string{ }, } +func getPathForFile(gameID uint32, classID uint32, categoryID uint32, slug string) string { + metaFolder := viper.GetString("meta-folder") + if metaFolder == "" { + if m, ok := defaultFolders[gameID]; ok { + if folder, ok := m[classID]; ok { + return filepath.Join(viper.GetString("meta-folder-base"), folder, slug+core.MetaExtension) + } else if folder, ok := m[categoryID]; ok { + return filepath.Join(viper.GetString("meta-folder-base"), folder, slug+core.MetaExtension) + } + } + metaFolder = "." + } + return filepath.Join(viper.GetString("meta-folder-base"), metaFolder, slug+core.MetaExtension) +} + func createModFile(modInfo modInfo, fileInfo modFileInfo, index *core.Index, optionalDisabled bool) error { updateMap := make(map[string]map[string]interface{}) var err error @@ -179,7 +194,7 @@ func createModFile(modInfo modInfo, fileInfo modFileInfo, index *core.Index, opt Option: optional, Update: updateMap, } - path := modMeta.SetMetaName(modInfo.Slug, *index) + path := modMeta.SetMetaPath(getPathForFile(modInfo.GameID, modInfo.ClassID, modInfo.PrimaryCategoryID, modInfo.Slug)) // If the file already exists, this will overwrite it!!! // TODO: Should this be improved? diff --git a/curseforge/import.go b/curseforge/import.go index 8b8bb91..b20ebb1 100644 --- a/curseforge/import.go +++ b/curseforge/import.go @@ -266,8 +266,7 @@ var importCmd = &cobra.Command{ os.Exit(1) } - // TODO: just use mods-folder directly? does texture pack importing affect this? - modFilePath := core.ResolveMod(modInfoValue.Slug, index) + modFilePath := getPathForFile(modInfoValue.GameID, modInfoValue.ClassID, modInfoValue.PrimaryCategoryID, modInfoValue.Slug) ref, err := filepath.Abs(filepath.Join(filepath.Dir(modFilePath), modFileInfoValue.FileName)) if err == nil { referencedModPaths = append(referencedModPaths, ref) diff --git a/curseforge/request.go b/curseforge/request.go index 5154f95..e8a3ba6 100644 --- a/curseforge/request.go +++ b/curseforge/request.go @@ -134,6 +134,9 @@ type modInfo struct { Summary string `json:"summary"` Slug string `json:"slug"` ID int `json:"id"` + GameID uint32 `json:"gameId"` + PrimaryCategoryID uint32 `json:"primaryCategoryId"` + ClassID uint32 `json:"classId"` LatestFiles []modFileInfo `json:"latestFiles"` GameVersionLatestFiles []struct { // TODO: check how twitch launcher chooses which one to use, when you are on beta/alpha channel?! diff --git a/modrinth/install.go b/modrinth/install.go index b405d50..796fdb7 100644 --- a/modrinth/install.go +++ b/modrinth/install.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/viper" "os" + "path/filepath" "regexp" "strings" @@ -207,10 +208,14 @@ func installVersion(mod Mod, version Version, pack core.Pack) error { Update: updateMap, } var path string + folder := viper.GetString("meta-folder") + if folder == "" { + folder = "mods" + } if mod.Slug != "" { - path = modMeta.SetMetaName(mod.Slug, index) + path = modMeta.SetMetaPath(filepath.Join(viper.GetString("meta-folder-base"), folder, mod.Slug+core.MetaExtension)) } else { - path = modMeta.SetMetaName(mod.Title, index) + path = modMeta.SetMetaPath(filepath.Join(viper.GetString("meta-folder-base"), folder, mod.Title+core.MetaExtension)) } // If the file already exists, this will overwrite it!!!