mirror of
https://github.com/packwiz/packwiz.git
synced 2025-04-19 21:16:30 +02:00
Abstract file access, implement zip reading
This commit is contained in:
parent
8956ec9bcb
commit
c853f0ff07
@ -1,6 +1,7 @@
|
|||||||
package curseforge
|
package curseforge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -18,6 +19,8 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: this file is a mess, I need to refactor it
|
||||||
|
|
||||||
type importPackFile interface {
|
type importPackFile interface {
|
||||||
Name() string
|
Name() string
|
||||||
Open() (io.ReadCloser, error)
|
Open() (io.ReadCloser, error)
|
||||||
@ -33,6 +36,13 @@ type importPackMetadata interface {
|
|||||||
GetFiles() ([]importPackFile, error)
|
GetFiles() ([]importPackFile, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type importPackSource interface {
|
||||||
|
GetFile(path string) (importPackFile, error)
|
||||||
|
//TODO: was GetFileList(base string), is it needed?
|
||||||
|
GetFileList() ([]importPackFile, error)
|
||||||
|
GetPackFile() importPackFile
|
||||||
|
}
|
||||||
|
|
||||||
// importCmd represents the import command
|
// importCmd represents the import command
|
||||||
var importCmd = &cobra.Command{
|
var importCmd = &cobra.Command{
|
||||||
Use: "import [modpack]",
|
Use: "import [modpack]",
|
||||||
@ -108,43 +118,49 @@ var importCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Check if file is a zip
|
// Check if file is a zip
|
||||||
if string(header) == "PK" {
|
if string(header) == "PK" {
|
||||||
fmt.Println("it do be a zip doe")
|
// Read the whole file (as bufio doesn't work for zips)
|
||||||
os.Exit(0)
|
zipData, err := ioutil.ReadAll(buf)
|
||||||
} else {
|
|
||||||
// Read the whole file (as we are going to parse it multiple times)
|
|
||||||
fileData, err := ioutil.ReadAll(buf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error reading file: %s\n", err)
|
fmt.Printf("Error reading file: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
// Get zip size
|
||||||
// Determine what format the file is
|
stat, err := f.Stat()
|
||||||
var jsonFile map[string]interface{}
|
|
||||||
err = json.Unmarshal(fileData, &jsonFile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error parsing JSON: %s\n", err)
|
fmt.Printf("Error reading file: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
zr, err := zip.NewReader(bytes.NewReader(zipData), stat.Size())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error parsing zip: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
isManifest := false
|
// Search the zip for minecraftinstance.json or manifest.json
|
||||||
if v, ok := jsonFile["manifestType"]; ok {
|
var metaFile *zip.File
|
||||||
isManifest = v.(string) == "minecraftModpack"
|
for _, v := range zr.File {
|
||||||
|
fileName := filepath.Base(v.Name)
|
||||||
|
if fileName == "minecraftinstance.json" || fileName == "manifest.json" {
|
||||||
|
metaFile = v
|
||||||
}
|
}
|
||||||
if isManifest {
|
}
|
||||||
fmt.Println("it do be a manifest doe")
|
|
||||||
os.Exit(0)
|
if metaFile == nil {
|
||||||
|
fmt.Println("Can't find manifest.json or minecraftinstance.json, is this a valid pack?")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
packImport = readMetadata(zipPackSource{
|
||||||
|
MetaFile: metaFile,
|
||||||
|
Reader: zr,
|
||||||
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Replace FileNameOnDisk with fileNameOnDisk
|
packImport = readMetadata(diskPackSource{
|
||||||
fileData = bytes.ReplaceAll(fileData, []byte("FileNameOnDisk"), []byte("fileNameOnDisk"))
|
MetaSource: buf,
|
||||||
packMeta := twitchInstalledPackMeta{}
|
MetaName: inputFile, // TODO: is this always the correct file?
|
||||||
err = json.Unmarshal(fileData, &packMeta)
|
BasePath: filepath.Dir(inputFile),
|
||||||
if err != nil {
|
})
|
||||||
fmt.Printf("Error parsing JSON: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
packMeta.srcFile = inputFile
|
|
||||||
packImport = packMeta
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +389,28 @@ func (f diskFile) Open() (io.ReadCloser, error) {
|
|||||||
return os.Open(f.Path)
|
return os.Open(f.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type zipReaderFile struct {
|
||||||
|
NameInternal string
|
||||||
|
*zip.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f zipReaderFile) Name() string {
|
||||||
|
return f.NameInternal
|
||||||
|
}
|
||||||
|
|
||||||
|
type readerFile struct {
|
||||||
|
NameInternal string
|
||||||
|
Reader *io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f readerFile) Name() string {
|
||||||
|
return f.NameInternal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f readerFile) Open() (io.ReadCloser, error) {
|
||||||
|
return *f.Reader, nil
|
||||||
|
}
|
||||||
|
|
||||||
func diskFilesFromPath(base string) ([]importPackFile, error) {
|
func diskFilesFromPath(base string) ([]importPackFile, error) {
|
||||||
list := make([]importPackFile, 0)
|
list := make([]importPackFile, 0)
|
||||||
err := filepath.Walk(base, func(path string, info os.FileInfo, err error) error {
|
err := filepath.Walk(base, func(path string, info os.FileInfo, err error) error {
|
||||||
@ -395,6 +433,60 @@ func diskFilesFromPath(base string) ([]importPackFile, error) {
|
|||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type diskPackSource struct {
|
||||||
|
MetaSource *bufio.Reader
|
||||||
|
MetaName string
|
||||||
|
BasePath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s diskPackSource) GetFile(path string) (importPackFile, error) {
|
||||||
|
return diskFile{s.BasePath, path}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s diskPackSource) GetFileList() ([]importPackFile, error) {
|
||||||
|
return diskFilesFromPath(s.BasePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s diskPackSource) GetPackFile() importPackFile {
|
||||||
|
rc := ioutil.NopCloser(s.MetaSource)
|
||||||
|
return readerFile{s.MetaName, &rc}
|
||||||
|
}
|
||||||
|
|
||||||
|
type zipPackSource struct {
|
||||||
|
MetaFile *zip.File
|
||||||
|
Reader *zip.Reader
|
||||||
|
cachedFileList []importPackFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s zipPackSource) GetFile(path string) (importPackFile, error) {
|
||||||
|
if s.cachedFileList == nil {
|
||||||
|
s.cachedFileList = make([]importPackFile, len(s.Reader.File))
|
||||||
|
for i, v := range s.Reader.File {
|
||||||
|
s.cachedFileList[i] = zipReaderFile{v.Name, v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range s.cachedFileList {
|
||||||
|
if v.Name() == path {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return zipReaderFile{}, errors.New("file not found in zip")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s zipPackSource) GetFileList() ([]importPackFile, error) {
|
||||||
|
if s.cachedFileList == nil {
|
||||||
|
s.cachedFileList = make([]importPackFile, len(s.Reader.File))
|
||||||
|
for i, v := range s.Reader.File {
|
||||||
|
s.cachedFileList[i] = zipReaderFile{v.Name, v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.cachedFileList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s zipPackSource) GetPackFile() importPackFile {
|
||||||
|
return zipReaderFile{s.MetaFile.Name, s.MetaFile}
|
||||||
|
}
|
||||||
|
|
||||||
type twitchInstalledPackMeta struct {
|
type twitchInstalledPackMeta struct {
|
||||||
NameInternal string `json:"name"`
|
NameInternal string `json:"name"`
|
||||||
Path string `json:"installPath"`
|
Path string `json:"installPath"`
|
||||||
@ -472,3 +564,51 @@ func (m twitchInstalledPackMeta) GetFiles() ([]importPackFile, error) {
|
|||||||
}
|
}
|
||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readMetadata(s importPackSource) importPackMetadata {
|
||||||
|
var packImport importPackMetadata
|
||||||
|
metaFile := s.GetPackFile()
|
||||||
|
rdr, err := metaFile.Open()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error reading file: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the whole file (as we are going to parse it multiple times)
|
||||||
|
fileData, err := ioutil.ReadAll(rdr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error reading file: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine what format the file is
|
||||||
|
var jsonFile map[string]interface{}
|
||||||
|
err = json.Unmarshal(fileData, &jsonFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error parsing JSON: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
isManifest := false
|
||||||
|
if v, ok := jsonFile["manifestType"]; ok {
|
||||||
|
isManifest = v.(string) == "minecraftModpack"
|
||||||
|
}
|
||||||
|
if isManifest {
|
||||||
|
fmt.Println("it do be a manifest doe")
|
||||||
|
os.Exit(0)
|
||||||
|
// TODO: implement manifest parsing
|
||||||
|
} else {
|
||||||
|
// Replace FileNameOnDisk with fileNameOnDisk
|
||||||
|
fileData = bytes.ReplaceAll(fileData, []byte("FileNameOnDisk"), []byte("fileNameOnDisk"))
|
||||||
|
packMeta := twitchInstalledPackMeta{}
|
||||||
|
err = json.Unmarshal(fileData, &packMeta)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error parsing JSON: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
packMeta.srcFile = metaFile.Name()
|
||||||
|
packImport = packMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
return packImport
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user