-
Notifications
You must be signed in to change notification settings - Fork 9
/
directory_tree.go
71 lines (66 loc) · 1.8 KB
/
directory_tree.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Package directory_tree provides a way to generate a directory tree.
//
// Example usage:
//
// tree, err := directory_tree.NewTree("/home/me")
//
// I did my best to keep it OS-independent but truth be told I only tested it
// on OS X and Debian Linux so YMMV. You've been warned.
package directory_tree
import (
"os"
"path/filepath"
"time"
)
// FileInfo is a struct created from os.FileInfo interface for serialization.
type FileInfo struct {
Name string `json:"name"`
Size int64 `json:"size"`
Mode os.FileMode `json:"mode"`
ModTime time.Time `json:"mod_time"`
IsDir bool `json:"is_dir"`
}
// Helper function to create a local FileInfo struct from os.FileInfo interface.
func fileInfoFromInterface(v os.FileInfo) *FileInfo {
return &FileInfo{v.Name(), v.Size(), v.Mode(), v.ModTime(), v.IsDir()}
}
// Node represents a node in a directory tree.
type Node struct {
FullPath string `json:"path"`
Info *FileInfo `json:"info"`
Children []*Node `json:"children"`
Parent *Node `json:"-"`
}
// Create directory hierarchy.
func NewTree(root string) (result *Node, err error) {
absRoot, err := filepath.Abs(root)
if err != nil {
return
}
parents := make(map[string]*Node)
walkFunc := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
parents[path] = &Node{
FullPath: path,
Info: fileInfoFromInterface(info),
Children: make([]*Node, 0),
}
return nil
}
if err = filepath.Walk(absRoot, walkFunc); err != nil {
return
}
for path, node := range parents {
parentPath := filepath.Dir(path)
parent, exists := parents[parentPath]
if !exists { // If a parent does not exist, this is the root.
result = node
} else {
node.Parent = parent
parent.Children = append(parent.Children, node)
}
}
return
}