88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
package fs
|
|
|
|
import (
|
|
"strings"
|
|
|
|
cmap "github.com/orcaman/concurrent-map/v2"
|
|
)
|
|
|
|
// FileNode represents a directory or a file. If IsDir is true, Children is used.
|
|
type FileNode struct {
|
|
Name string
|
|
IsDir bool
|
|
Children cmap.ConcurrentMap[string, *FileNode]
|
|
}
|
|
|
|
// NewFileNode creates a new FileNode, initializing the concurrent map if it is a directory.
|
|
func NewFileNode(name string, isDir bool) *FileNode {
|
|
node := &FileNode{
|
|
Name: name,
|
|
IsDir: isDir,
|
|
}
|
|
if isDir {
|
|
node.Children = cmap.New[*FileNode]()
|
|
}
|
|
return node
|
|
}
|
|
|
|
// AddChild adds a child node to a directory node.
|
|
func (n *FileNode) AddChild(child *FileNode) {
|
|
if n.IsDir {
|
|
n.Children.Set(child.Name, child)
|
|
}
|
|
}
|
|
|
|
// AddPath adds a path to the file system like mkdir -p.
|
|
func (n *FileNode) MakeDirectoryWithPath(path string) {
|
|
currentNode := n
|
|
for _, part := range SplitPath(path) {
|
|
child, ok := currentNode.Children.Get(part)
|
|
if !ok {
|
|
child = NewFileNode(part, true)
|
|
currentNode.AddChild(child)
|
|
}
|
|
currentNode = child
|
|
}
|
|
}
|
|
|
|
// AddChildToPath adds a child to a path in the file system. Path should be an existing directory.
|
|
func (n *FileNode) AddChildToPath(path string, child *FileNode) {
|
|
parent := n.GetFileNode(path)
|
|
if parent != nil && parent.IsDir {
|
|
parent.AddChild(child)
|
|
}
|
|
}
|
|
|
|
// ListFiles returns a list of files in the file system.
|
|
func (n *FileNode) ListFiles() []*FileNode {
|
|
var files []*FileNode
|
|
n.Children.IterCb(func(key string, value *FileNode) {
|
|
files = append(files, value)
|
|
})
|
|
return files
|
|
}
|
|
|
|
// GetFileNode returns the FileNode of the given path.
|
|
func (n *FileNode) GetFileNode(path string) *FileNode {
|
|
currentNode := n
|
|
for _, part := range SplitPath(path) {
|
|
child, ok := currentNode.Children.Get(part)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
currentNode = child
|
|
}
|
|
return currentNode
|
|
}
|
|
|
|
// SplitPath splits a path into its parts.
|
|
func SplitPath(path string) []string {
|
|
var parts []string
|
|
for _, part := range strings.Split(path, "/") {
|
|
if part != "" {
|
|
parts = append(parts, part)
|
|
}
|
|
}
|
|
return parts
|
|
}
|