Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.8 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/anacrolix/generics v0.0.0-20230113004304-d6428d516633 // indirect
github.com/anacrolix/log v0.14.1 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
Expand Down
53 changes: 53 additions & 0 deletions internal/catalog/catalog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package catalog

import (
"gocatcli/internal/tree"
"path/filepath"
)

const (
jsonExt = ".json"
tomlExt = ".toml"
sqliteExt = ".sqlite" // TODO
catalogExt = ".catalog"
)

type Backend interface {
Serialize(t *tree.Tree) ([]byte, error)
Save(path string, t *tree.Tree) error
LoadTree(path string) (*tree.Tree, error)
}

type Catalog struct {
Path string
B Backend
}

func (c *Catalog) Serialize(t *tree.Tree) ([]byte, error) {
return c.B.Serialize(t)
}

func (c *Catalog) Save(t *tree.Tree) error {
return c.B.Save(c.Path, t)
}

func (c *Catalog) LoadTree() (*tree.Tree, error) {
return c.B.LoadTree(c.Path)
}

func NewCatalog(path string) *Catalog {
var b Backend
ext := filepath.Ext(path)
if ext == catalogExt {
b = NewTOMLBackend()
} else if ext == jsonExt {
b = NewJSONBackend()
} else if ext == tomlExt {
b = NewTOMLBackend()
}
c := Catalog{
Path: path,
B: b,
}
return &c
}
76 changes: 76 additions & 0 deletions internal/catalog/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package catalog

import (
"encoding/json"
"gocatcli/internal/log"
"gocatcli/internal/tree"
"os"
"time"
)

var (
jsonIndent bool = true
)

// JSONBackend the JSON backend
type JSONBackend struct{}

// Serialize gets the tree as string
func (b *JSONBackend) Serialize(t *tree.Tree) ([]byte, error) {
t.Updated = time.Now().Unix()

var content []byte
var err error
if jsonIndent {
content, err = json.MarshalIndent(t, "", " ")
} else {
content, err = json.Marshal(t)
}
if err != nil {
log.Debugf("marshal failed: %v", err)
return nil, err
}

return content, err
}

// Save saves a tree to json
func (b *JSONBackend) Save(path string, t *tree.Tree) error {
log.Debug("serialize tree...")
content, err := b.Serialize(t)
if err != nil {
return err
}

log.Debugf("write tree to \"%s\"...", path)
err = os.WriteFile(path, content, os.ModePerm)
if err != nil {
return err
}
log.Debugf("tree saved to \"%s\"", path)
return nil
}

// LoadTree loads a tree from json
func (b *JSONBackend) LoadTree(path string) (*tree.Tree, error) {
log.Debugf("loading catalog from %s", path)
fd, err := os.Open(path)
if err != nil {
return nil, err
}
defer fd.Close()

var tree tree.Tree
err = json.NewDecoder(fd).Decode(&tree)
if err != nil {
return nil, err
}

return &tree, nil
}

// NewJSONBackend creates a new json backend
func NewJSONBackend() *JSONBackend {
b := &JSONBackend{}
return b
}
62 changes: 62 additions & 0 deletions internal/catalog/toml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package catalog

import (
"bytes"
"gocatcli/internal/log"
"gocatcli/internal/tree"
"os"
"time"

"github.com/BurntSushi/toml"
)

// TOMLBackend the toml backend
type TOMLBackend struct{}

// Serialize gets the tree as string
func (b *TOMLBackend) Serialize(t *tree.Tree) ([]byte, error) {
t.Updated = time.Now().Unix()

buf := new(bytes.Buffer)
err := toml.NewEncoder(buf).Encode(t)
if err != nil {
log.Debugf("marshal failed: %v", err)
return nil, err
}
return buf.Bytes(), err
}

// Save saves a tree to toml
func (b *TOMLBackend) Save(path string, t *tree.Tree) error {
log.Debug("serialize tree...")
content, err := b.Serialize(t)
if err != nil {
return err
}

log.Debugf("write tree to \"%s\"...", path)
err = os.WriteFile(path, content, os.ModePerm)
if err != nil {
return err
}
log.Debugf("tree saved to \"%s\"", path)
return nil
}

// LoadTree loads a tree from toml
func (b *TOMLBackend) LoadTree(path string) (*tree.Tree, error) {
log.Debugf("loading catalog from %s", path)
var tree tree.Tree
_, err := toml.DecodeFile(path, &tree)
if err != nil {
return nil, err
}

return &tree, nil
}

// NewTOMLBackend creates a new toml backend
func NewTOMLBackend() *TOMLBackend {
b := &TOMLBackend{}
return b
}
12 changes: 7 additions & 5 deletions internal/commands/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package commands

import (
"fmt"
"gocatcli/internal/catalog"
"gocatcli/internal/catcli"
"gocatcli/internal/utils"

Expand All @@ -22,14 +23,14 @@ var (
RunE: convert,
}

convertOptTo string
convertOptOutput string
convertOptIndent bool
)

func init() {
rootCmd.AddCommand(convertCmd)

convertCmd.PersistentFlags().StringVarP(&convertOptTo, "output", "o", "", "output path")
convertCmd.PersistentFlags().StringVarP(&convertOptOutput, "output", "o", "", "output path")
convertCmd.PersistentFlags().BoolVarP(&convertOptIndent, "indent", "I", true, "do not indent json")
}

Expand All @@ -44,11 +45,12 @@ func convert(_ *cobra.Command, args []string) error {
return err
}

if len(convertOptTo) > 0 {
return t.Save(convertOptTo, convertOptIndent)
if len(convertOptOutput) > 0 {
c := catalog.NewCatalog(convertOptOutput)
return c.Save(t)
}

content, err := t.Serialize(convertOptIndent)
content, err := rootCatalog.Serialize(t)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func create(_ *cobra.Command, args []string) error {
return fmt.Errorf("no such start path: \"%s\"", createOptStart)
}
} else {
for _, top := range loadedTree.GetStorages() {
for _, top := range rootTree.GetStorages() {
startNodes = append(startNodes, top)
}
}
Expand Down Expand Up @@ -138,7 +138,7 @@ func create(_ *cobra.Command, args []string) error {
return true
}

loadedTree.ProcessChildren(n, true, callback, -1)
rootTree.ProcessChildren(n, true, callback, -1)
}
return nil
}
6 changes: 3 additions & 3 deletions internal/commands/du.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func diskUsage(_ *cobra.Command, args []string) error {
return fmt.Errorf("no such start path: \"%s\"", path)
}
} else {
for _, top := range loadedTree.GetStorages() {
for _, top := range rootTree.GetStorages() {
startNodes = append(startNodes, top)
}
}
Expand All @@ -63,7 +63,7 @@ func diskUsage(_ *cobra.Command, args []string) error {
RawSize: duOptRawSize,
Separator: separator,
}
stringer := stringer.NewDuStringer(loadedTree, m)
stringer := stringer.NewDuStringer(rootTree, m)
for _, n := range startNodes {
var nodes []node.Node
callback := func(n node.Node, _ int, _ node.Node) bool {
Expand All @@ -79,7 +79,7 @@ func diskUsage(_ *cobra.Command, args []string) error {
return true
}

loadedTree.ProcessChildren(n, true, callback, duOptDepth)
rootTree.ProcessChildren(n, true, callback, duOptDepth)
if len(nodes) > 0 {
slices.SortFunc(nodes, func(left, right node.Node) int {
return cmp.Compare(left.GetSize(), right.GetSize())
Expand Down
6 changes: 3 additions & 3 deletions internal/commands/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func find(_ *cobra.Command, args []string) error {
RawSize: false,
Separator: separator,
}
stringGetter, err := stringer.GetStringer(loadedTree, findOptFormat, m)
stringGetter, err := stringer.GetStringer(rootTree, findOptFormat, m)
if err != nil {
return err
}
Expand All @@ -76,7 +76,7 @@ func find(_ *cobra.Command, args []string) error {
return fmt.Errorf("no such start path: \"%s\"", findOptStart)
}
} else {
for _, top := range loadedTree.GetStorages() {
for _, top := range rootTree.GetStorages() {
startNodes = append(startNodes, top)
}
}
Expand All @@ -93,7 +93,7 @@ func find(_ *cobra.Command, args []string) error {
log.Debugf("search pattern: %s", patt)

for _, startNode := range startNodes {
matchNodes(loadedTree, startNode, re, stringGetter)
matchNodes(rootTree, startNode, re, stringGetter)
}
}

Expand Down
10 changes: 5 additions & 5 deletions internal/commands/fzfind.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func fzFind(_ *cobra.Command, args []string) error {
RawSize: false,
Separator: separator,
}
stringGetter, err := stringer.GetStringer(loadedTree, fzFindOptFormat, m)
stringGetter, err := stringer.GetStringer(rootTree, fzFindOptFormat, m)
if err != nil {
return err
}
Expand All @@ -76,7 +76,7 @@ func fzFind(_ *cobra.Command, args []string) error {
return fmt.Errorf("no such start path: \"%s\"", startPath)
}
} else {
for _, top := range loadedTree.GetStorages() {
for _, top := range rootTree.GetStorages() {
startNodes = append(startNodes, top)
}
}
Expand Down Expand Up @@ -141,7 +141,7 @@ func fzFind(_ *cobra.Command, args []string) error {
stringGetter.PrintPrefix()
stringGetter.Print(entry.item, 0)
if hasChildren {
loadedTree.ProcessChildren(entry.item, fzFindOptShowAll, callback, 1)
rootTree.ProcessChildren(entry.item, fzFindOptShowAll, callback, 1)
}
stringGetter.PrintSuffix()
}
Expand All @@ -151,7 +151,7 @@ func fzFind(_ *cobra.Command, args []string) error {

func fzFindFillList(n node.Node) []*fzfEntry {
var list []*fzfEntry
top := loadedTree.GetStorageNode(n)
top := rootTree.GetStorageNode(n)
callback := func(n node.Node, _ int, _ node.Node) bool {
item := &fzfEntry{
Path: filepath.Join(top.GetName(), n.GetPath()),
Expand All @@ -161,6 +161,6 @@ func fzFindFillList(n node.Node) []*fzfEntry {
list = append(list, item)
return true
}
loadedTree.ProcessChildren(n, fzFindOptShowAll, callback, -1)
rootTree.ProcessChildren(n, fzFindOptShowAll, callback, -1)
return list
}
4 changes: 2 additions & 2 deletions internal/commands/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

func getStartPaths(path string) []node.Node {
log.Debugf("getting start paths from \"%s\"", path)
storages := loadedTree.GetStorages()
storages := rootTree.GetStorages()
// do not mess with pattern
if !strings.Contains(path, "*") && len(storages) == 1 {
// complete if single storage
Expand All @@ -23,5 +23,5 @@ func getStartPaths(path string) []node.Node {
path = filepath.Join(name, path)
}
}
return loadedTree.GetNodesFromPath(path)
return rootTree.GetNodesFromPath(path)
}
Loading