86 lines
1.8 KiB
Go
Executable File
86 lines
1.8 KiB
Go
Executable File
package files
|
|
|
|
import (
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
"ddc/internal/extract"
|
|
)
|
|
|
|
const (
|
|
maxTreeEntries = 20000
|
|
maxTreeDepth = 32
|
|
)
|
|
|
|
type Node struct {
|
|
Name string `json:"name"`
|
|
Path string `json:"path"`
|
|
IsDir bool `json:"isDir"`
|
|
IsArchive bool `json:"isArchive"`
|
|
Size int64 `json:"size"`
|
|
Children []Node `json:"children,omitempty"`
|
|
}
|
|
|
|
func BuildTree(root string) ([]Node, error) {
|
|
entryCount := 0
|
|
return readLevel(root, "", 0, &entryCount)
|
|
}
|
|
|
|
func readLevel(root, relative string, depth int, entryCount *int) ([]Node, error) {
|
|
entries, err := os.ReadDir(filepath.Join(root, relative))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nodes := make([]Node, 0, len(entries))
|
|
for _, entry := range entries {
|
|
if *entryCount >= maxTreeEntries {
|
|
break
|
|
}
|
|
entryType := entry.Type()
|
|
if entry.Name() == PartFileName || (!entryType.IsDir() && !entryType.IsRegular()) {
|
|
continue
|
|
}
|
|
*entryCount++
|
|
|
|
node := Node{
|
|
Name: entry.Name(),
|
|
Path: path.Join(filepath.ToSlash(relative), entry.Name()),
|
|
IsDir: entry.IsDir(),
|
|
}
|
|
|
|
if node.IsDir {
|
|
if depth < maxTreeDepth {
|
|
children, err := readLevel(root, filepath.Join(relative, entry.Name()), depth+1, entryCount)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
node.Children = children
|
|
for _, child := range children {
|
|
node.Size += child.Size
|
|
}
|
|
}
|
|
} else {
|
|
info, err := entry.Info()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
node.Size = info.Size()
|
|
node.IsArchive = extract.IsArchive(entry.Name())
|
|
}
|
|
|
|
nodes = append(nodes, node)
|
|
}
|
|
|
|
sort.SliceStable(nodes, func(first, second int) bool {
|
|
if nodes[first].IsDir != nodes[second].IsDir {
|
|
return nodes[first].IsDir
|
|
}
|
|
return strings.ToLower(nodes[first].Name) < strings.ToLower(nodes[second].Name)
|
|
})
|
|
return nodes, nil
|
|
}
|