Skip to content

Commit

Permalink
feat: add by-tag resource listing to cli
Browse files Browse the repository at this point in the history
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
  • Loading branch information
Ryex committed Oct 1, 2024
1 parent e31fea7 commit 9a10975
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 66 deletions.
7 changes: 7 additions & 0 deletions internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ func (ctx *Context) LoadPkg(path string) error {
ctx.Log.WithError(err).Error("failed to load package")
return err
}
errs := ctx.Pkg.BuildFileList()
if len(errs) != 0 {
for _, err := range errs {
ctx.Log.WithField("task", "building file list").Errorf("error : %s", err.Error())
}
return errors.Join(errs...)
}
} else {
err := ctx.Pkg.LoadFromPackedPath(ctx.InputPath, nil)
if err != nil {
Expand Down
129 changes: 91 additions & 38 deletions internal/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,91 @@ import (
"github.com/sirupsen/logrus"
treeprint "github.com/xlab/treeprint"

"github.com/ryex/dungeondraft-gopackager/internal/utils"
"github.com/ryex/dungeondraft-gopackager/pkg/ddpackage"
"github.com/ryex/dungeondraft-gopackager/pkg/structures"
)

type ListCmd struct {
Files ListFilesCmd `cmd:"" help:"lists files in the pack"`
Tags ListTagsCmd `cmd:"" help:"lists all tags that match the provided resource patterns. with no patterns lists all tags"`
Sets ListSetsCmd `cmd:"" help:"List tag sets or the tags for a set"`
}

type ListFilesCmd struct {
All bool `short:"A" help:"List all file in the package, overrides the individual type options"`
Textures bool `short:"X" default:"true" negatable:"" help:"list texture files. default is true but negatable with --no-textures"`
Thumbnails bool `short:"T" default:"false" negatable:"" help:"list thumbnail files"`
Data bool `short:"D" default:"false" negatable:"" help:"list Data files (tags, and wall/terrain metadata )"`
Type string `enum:"tree,list" default:"tree" help:"print the files in a resource path tree or a list as packed"`
InputPath string `arg:"" type:"path" help:"the .dungeondraft_pack file or resource directory to work with"`
All bool `short:"A" help:"List all file in the package, overrides the individual type options"`
Textures bool `short:"X" default:"true" negatable:"" help:"list texture files. default is true but negatable with --no-textures"`
Thumbnails bool `short:"T" default:"false" negatable:"" help:"list thumbnail files"`
Data bool `short:"D" default:"false" negatable:"" help:"list Data files (tags, and wall/terrain metadata )"`
Type string `enum:"tree,list" default:"list" help:"print the files in a resource path tree or a list as packed"`
InputPath string `arg:"" type:"path" help:"the .dungeondraft_pack file or resource directory to work with"`
ByTag []string `short:"t" help:"List objects that match these tags (comma separated)"`
Globs []string `arg:"" optional:"" help:"optional glob patterns to filter the output by"`
}

func (lsf *ListFilesCmd) Run(ctx *Context) error {
err := ctx.LoadPkg(lsf.InputPath)
if err != nil {
return err
}

filterFunc := func(fi *structures.FileInfo) bool {
if fi.IsMetadata() && !lsf.All {
return false
}
if fi.IsTexture() && (!lsf.Textures && !lsf.All) {
return false
}
if fi.IsThumbnail() && (!lsf.Thumbnails && !lsf.All) {
return false
}
if fi.IsData() && (!lsf.Data && !lsf.All) {
return false
}
return true
}

fileList := ctx.Pkg.FileList()
if len(lsf.ByTag) > 0 {
ctx.Pkg.LoadTags()
fileList = fileList.Filter(func(fi *structures.FileInfo) bool {
if !fi.IsObject() {
return false
}
tags := ctx.Pkg.Tags().TagsFor(fi.CalcRelPath())
return utils.Any(lsf.ByTag, func(searchTag string) bool {
return tags.Has(searchTag)
})
})
}
if len(lsf.Globs) > 0 {
var err error
fileList, err = fileList.Glob(filterFunc, lsf.Globs...)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
} else {
fileList = fileList.Filter(filterFunc)
}

if lsf.Type == "tree" {
lsf.printTree(ctx.Log, ctx.Pkg)
lsf.printTree(ctx.Log, fileList)
} else {
lsf.printList(ctx.Pkg)
lsf.printList(fileList)
}
return nil
}

func (lsf *ListFilesCmd) printList(pkg *ddpackage.Package) {
fileList := pkg.FileList()
filesCount := len(fileList)
for i, fi := range fileList {
fmt.Printf(
"File [%-5d/%-5d] Name: %-38s Size: %-8d Offset %-8d ResourcePath: %s\n",
i+1,
filesCount,
filepath.Base(fi.ResPath),
fi.Size,
fi.Offset,
fi.ResPath,
)
func (lsf *ListFilesCmd) printList(list structures.FileInfoList) {
for _, fi := range list {
fmt.Fprintln(os.Stdout, fi.ResPath)
}
}

func (lsf *ListFilesCmd) printTree(l logrus.FieldLogger, pkg *ddpackage.Package) {
func (lsf *ListFilesCmd) printTree(
l logrus.FieldLogger,
list structures.FileInfoList,
) {
tree := treeprint.New()
branchMap := make(map[string]treeprint.Tree)

Expand Down Expand Up @@ -91,21 +128,8 @@ func (lsf *ListFilesCmd) printTree(l logrus.FieldLogger, pkg *ddpackage.Package)
return branchMap[path]
}
}
fileList := pkg.FileList()
for i, fi := range fileList {
if fi.IsMetadata() && !lsf.All {
continue
}
if fi.IsTexture() && (!lsf.Textures && !lsf.All) {
continue
}
if fi.IsThumbnail() && (!lsf.Thumbnails && !lsf.All) {
continue
}
if fi.IsData() && (!lsf.Data && !lsf.All) {
continue
}
path := pkg.NormalizeResourcePath(fi.ResPath)
for i, fi := range list {
path := utils.NormalizeResourcePath(fi.ResPath)
l.WithField("res", fi.ResPath).
WithField("size", fi.Size).
WithField("index", i).
Expand Down Expand Up @@ -138,7 +162,7 @@ func (ls *ListTagsCmd) printTags(l logrus.FieldLogger, pkg *ddpackage.Package) e
if len(ls.GlobPatterns) < 1 {
tags = pkg.Tags().AllTags()
} else {
files, err := pkg.FileList().Glob(func(fi *structures.FileInfo) bool { return fi.IsTexture() }, ls.GlobPatterns...)
files, err := pkg.FileList().Glob(func(fi *structures.FileInfo) bool { return fi.IsObject() }, ls.GlobPatterns...)
if err != nil {
l.WithError(err).Error("failed to glob file list")
return err
Expand All @@ -150,3 +174,32 @@ func (ls *ListTagsCmd) printTags(l logrus.FieldLogger, pkg *ddpackage.Package) e
}
return nil
}

type ListSetsCmd struct {
InputPath string `arg:"" type:"path" help:"the .dungeondraft_pack file or resource directory to work with"`
TagSet string `arg:"" optional:"" help:"an optional tag set to list tags for"`
}

func (lsc *ListSetsCmd) Run(ctx *Context) error {
err := ctx.LoadPkg(lsc.InputPath)
if err != nil {
return err
}
err = ctx.LoadTags()
if err != nil {
return err
}
if lsc.TagSet == "" {
for _, set := range ctx.Pkg.Tags().AllSets() {
fmt.Fprintln(os.Stdout, set)
}
} else {
set := ctx.Pkg.Tags().Set(lsc.TagSet)
if set != nil {
for _, tag := range set.AsSlice() {
fmt.Fprintln(os.Stdout, tag)
}
}
}
return nil
}
4 changes: 2 additions & 2 deletions internal/gui/pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ func (a *App) packPackage(path string, options ddpackage.PackOptions, genThumbna
if genThumbnails {
taskStr.Set(lang.X("task.genthumbnails.text", "Generating thumbnails ..."))
a.packageWatcherIgnoreThumbnails = true
err := a.pkg.GenerateThumbnails(func(p float64) {
err := a.pkg.GenerateThumbnailsProgress(func(p float64) {
progressVal.Set(p)
})
if err != nil {
Expand All @@ -420,7 +420,7 @@ func (a *App) packPackage(path string, options ddpackage.PackOptions, genThumbna
}

taskStr.Set(lang.X("task.package.text", "Packaging resources ..."))
err := a.pkg.PackPackage(path, options, func(p float64) {
err := a.pkg.PackPackageProgress(path, options, func(p float64) {
progressVal.Set(p)
})
progressDlg.Hide()
Expand Down
2 changes: 1 addition & 1 deletion internal/gui/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (a *App) extractPackage(path string, options ddpackage.UnpackOptions) {
)
progressDlg.Show()
go func() {
err := a.pkg.ExtractPackage(path, options, func(p float64) {
err := a.pkg.ExtractPackageProgress(path, options, func(p float64) {
log.Info(p)
progressVal.Set(p)
})
Expand Down
33 changes: 33 additions & 0 deletions internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -196,6 +197,24 @@ func Filter[T any](ts []T, P func(T) bool) []T {
return ret
}

func Any[T any](ts []T, P func(T) bool) bool {
for _, t := range ts {
if P(t) {
return true
}
}
return false
}

func All[T any](ts []T, P func(T) bool) bool {
for _, t := range ts {
if !P(t) {
return false
}
}
return true
}

func ListDir(path string) (files []string, dirs []string, errs []error) {
paths := []string{path}

Expand Down Expand Up @@ -231,3 +250,17 @@ func PathIsSub(parent string, sub string) (bool, error) {
}
return false, nil
}

var (
PackJSONPathRegex = regexp.MustCompile(`^res://packs/([\w\-. ]+).json`)
IDTrimPrefixRegex = regexp.MustCompile(`^([\w\-. ]+)/`)
)

func NormalizeResourcePath(resPath string) string {
if match := PackJSONPathRegex.MatchString(resPath); match {
return "pack.json"
}
path := strings.TrimPrefix(resPath, "res://packs/")
path = IDTrimPrefixRegex.ReplaceAllString(path, "")
return filepath.Clean(path)
}
6 changes: 3 additions & 3 deletions pkg/ddpackage/pack_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ func (p *Package) SaveUnpackedWall(resPath string) error {
return nil
}

p.log.Infof("%s normalised to %s", resPath, p.NormalizeResourcePath(resPath))
p.log.Infof("%s normalised to %s", resPath, utils.NormalizeResourcePath(resPath))

wallDataPath := filepath.Join(p.unpackedPath, p.NormalizeResourcePath(resPath))
wallDataPath := filepath.Join(p.unpackedPath, utils.NormalizeResourcePath(resPath))

l := p.log.WithField("res", wallDataPath)
l.Info("saving wall")
Expand Down Expand Up @@ -170,7 +170,7 @@ func (p *Package) SaveUnpackedTileset(resPath string) error {
return nil
}

tilesetDataPath := filepath.Join(p.unpackedPath, p.NormalizeResourcePath(resPath))
tilesetDataPath := filepath.Join(p.unpackedPath, utils.NormalizeResourcePath(resPath))

l := p.log.WithField("res", tilesetDataPath)
l.Info("saving tileset")
Expand Down
19 changes: 2 additions & 17 deletions pkg/ddpackage/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"os"
"path/filepath"
"reflect"
"regexp"
"strings"

"github.com/ryex/dungeondraft-gopackager/internal/utils"
Expand Down Expand Up @@ -50,23 +49,9 @@ func (p *Package) extractPackage(
return
}

var (
packJSONPathRegex = regexp.MustCompile(`^res://packs/([\w\-. ]+).json`)
idTrimPrefixRegex = regexp.MustCompile(`^([\w\-. ]+)/`)
)

func (p *Package) NormalizeResourcePath(resPath string) string {
if match := packJSONPathRegex.MatchString(resPath); match {
return "pack.json"
}
path := strings.TrimPrefix(resPath, "res://packs/")
path = idTrimPrefixRegex.ReplaceAllString(path, "")
return filepath.Clean(path)
}

func (p *Package) MapResourcePaths() {
for _, fi := range p.fileList {
fi.Path = p.NormalizeResourcePath(fi.ResPath)
fi.Path = utils.NormalizeResourcePath(fi.ResPath)
}
}

Expand Down Expand Up @@ -287,7 +272,7 @@ func (p *Package) loadPackedPackJSON(r io.ReadSeeker) (err error) {
}
var packJSONInfo *structures.FileInfo
for _, fi := range p.fileList {
match := packJSONPathRegex.MatchString(fi.ResPath)
match := utils.PackJSONPathRegex.MatchString(fi.ResPath)
if match {
packJSONInfo = fi
break
Expand Down
17 changes: 12 additions & 5 deletions pkg/structures/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (fil FileInfoList) GetRessource(path string) *FileInfo {
return nil
}

func (fil FileInfoList) Find(P func(info *FileInfo) bool) *FileInfo {
func (fil FileInfoList) Find(P func(fi *FileInfo) bool) *FileInfo {
for _, fi := range fil {
if P(fi) {
return fi
Expand All @@ -177,7 +177,7 @@ func (fil FileInfoList) Find(P func(info *FileInfo) bool) *FileInfo {
return nil
}

func (fil FileInfoList) Filter(P func(info *FileInfo) bool) FileInfoList {
func (fil FileInfoList) Filter(P func(fi *FileInfo) bool) FileInfoList {
res := []*FileInfo{}
for _, fi := range fil {
if P(fi) {
Expand Down Expand Up @@ -262,7 +262,7 @@ var ErrBadFileInfoListGlobPattern = errors.New("could not compile glob pattern")
type FileInfoFilterFunc func(*FileInfo) bool

func (fil FileInfoList) Glob(filter FileInfoFilterFunc, patterns ...string) (FileInfoList, error) {
matches := []*FileInfo{}
matches := make(map[string]*FileInfo)

for _, pattern := range patterns {
regexpPat, err := GlobToRelPathRegexp(pattern)
Expand All @@ -277,12 +277,19 @@ func (fil FileInfoList) Glob(filter FileInfoFilterFunc, patterns ...string) (Fil
}
relPath := info.CalcRelPath()
if regexpPat.MatchString(relPath) {
matches = append(matches, info)
matches[info.ResPath] = info
}
}
}

return matches, nil
matchesS := make([]*FileInfo, len(matches))
i := 0
for _, fi := range matches {
matchesS[i] = fi
i++
}

return matchesS, nil
}

func (fil FileInfoList) Paths() (paths []string) {
Expand Down

0 comments on commit 9a10975

Please sign in to comment.