diff --git a/filetree/node.go b/filetree/node.go index f051a6b..95cc854 100644 --- a/filetree/node.go +++ b/filetree/node.go @@ -44,6 +44,7 @@ func NewNode(parent *FileNode, name string, data FileInfo) (node *FileNode) { if parent != nil { node.Tree = parent.Tree } + return node } @@ -85,6 +86,11 @@ func (node *FileNode) Copy(parent *FileNode) *FileNode { // AddChild creates a new node relative to the current FileNode. func (node *FileNode) AddChild(name string, data FileInfo) (child *FileNode) { + // never allow processing of purely whiteout flag files (for now) + if strings.HasPrefix(name, doubleWhiteoutPrefix) { + return nil + } + child = NewNode(node, name, data) if node.Children[name] != nil { // tree node already exists, replace the payload, keep the children @@ -93,6 +99,7 @@ func (node *FileNode) AddChild(name string, data FileInfo) (child *FileNode) { node.Children[name] = child node.Tree.Size++ } + return child } @@ -229,7 +236,7 @@ func (node *FileNode) IsLeaf() bool { // Path returns a slash-delimited string from the root of the greater tree to the current node (e.g. /a/path/to/here) func (node *FileNode) Path() string { if node.path == "" { - path := []string{} + var path []string curNode := node for { if curNode.Parent == nil { diff --git a/filetree/node_test.go b/filetree/node_test.go index 0963ce6..1111444 100644 --- a/filetree/node_test.go +++ b/filetree/node_test.go @@ -95,13 +95,18 @@ func TestIsWhiteout(t *testing.T) { tree1 := NewFileTree() p1, _ := tree1.AddPath("/etc/nginx/public1", FileInfo{}) p2, _ := tree1.AddPath("/etc/nginx/.wh.public2", FileInfo{}) + p3, _ := tree1.AddPath("/etc/nginx/public3/.wh..wh..opq", FileInfo{}) if p1.IsWhiteout() != false { - t.Errorf("Expected Path '%s' to **not** be a whiteout file", p1.Name) + t.Errorf("Expected path '%s' to **not** be a whiteout file", p1.Name) } if p2.IsWhiteout() != true { - t.Errorf("Expected Path '%s' to be a whiteout file", p2.Name) + t.Errorf("Expected path '%s' to be a whiteout file", p2.Name) + } + + if p3 != nil { + t.Errorf("Expected to not be able to add path '%s'", p2.Name) } } diff --git a/filetree/tree.go b/filetree/tree.go index adcf3af..4a6f32c 100644 --- a/filetree/tree.go +++ b/filetree/tree.go @@ -3,19 +3,21 @@ package filetree import ( "fmt" "github.com/satori/go.uuid" + "github.com/sirupsen/logrus" "sort" "strings" ) const ( - newLine = "\n" - noBranchSpace = " " - branchSpace = "│ " - middleItem = "├─" - lastItem = "└─" - whiteoutPrefix = ".wh." - uncollapsedItem = "─ " - collapsedItem = "⊕ " + newLine = "\n" + noBranchSpace = " " + branchSpace = "│ " + middleItem = "├─" + lastItem = "└─" + whiteoutPrefix = ".wh." + doubleWhiteoutPrefix = ".wh..wh.." + uncollapsedItem = "─ " + collapsedItem = "⊕ " ) // FileTree represents a set of files, directories, and their relations. @@ -218,6 +220,11 @@ func (tree *FileTree) AddPath(path string, data FileInfo) (*FileNode, error) { // don't attach the payload. The payload is destined for the // Path's end node, not any intermediary node. node = node.AddChild(name, FileInfo{}) + + if node == nil { + // the child could not be added + return node, fmt.Errorf(fmt.Sprintf("could not add child node '%s'", name)) + } } // attach payload to the last specified node @@ -277,7 +284,10 @@ func (tree *FileTree) markRemoved(path string) error { func StackRange(trees []*FileTree, start, stop int) *FileTree { tree := trees[0].Copy() for idx := start; idx <= stop; idx++ { - tree.Stack(trees[idx]) + err := tree.Stack(trees[idx]) + if err != nil { + logrus.Debug("could not stack tree range:", err) + } } return tree diff --git a/filetree/tree_test.go b/filetree/tree_test.go index 2a00b69..186d19e 100644 --- a/filetree/tree_test.go +++ b/filetree/tree_test.go @@ -187,6 +187,8 @@ func TestStack(t *testing.T) { // whiteout the following files tree2.AddPath("/var/run/.wh.bashful", FileInfo{}) tree2.AddPath("/.wh.tmp", FileInfo{}) + // ignore opaque whiteout files entirely + tree2.AddPath("/.wh..wh..opq", FileInfo{}) err := tree1.Stack(tree2)