Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overwrite lower tree payload while comparing/marking trees #161

Merged
merged 1 commit into from
Feb 18, 2019
Merged
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 .data/Dockerfile.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ ADD .scripts/ /root/.data/
RUN cp /root/saved.txt /tmp/saved.again1.txt
RUN cp /root/saved.txt /root/.data/saved.again2.txt
RUN chmod +x /root/saved.txt
RUN chmod 421 /root
3 changes: 1 addition & 2 deletions filetree/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ func (cache *TreeCache) Get(bottomTreeStart, bottomTreeStop, topTreeStart, topTr

func (cache *TreeCache) buildTree(key TreeCacheKey) *FileTree {
newTree := StackTreeRange(cache.refTrees, key.bottomTreeStart, key.bottomTreeStop)

for idx := key.topTreeStart; idx <= key.topTreeStop; idx++ {
newTree.Compare(cache.refTrees[idx])
newTree.CompareAndMark(cache.refTrees[idx])
}
return newTree
}
Expand Down
10 changes: 8 additions & 2 deletions filetree/efficiency.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ func Efficiency(trees []*FileTree) (float64, EfficiencySlice) {
if err != nil {
logrus.Debug(fmt.Sprintf("CurrentTree: %d : %s", currentTree, err))
} else if previousTreeNode.Data.FileInfo.IsDir {
previousTreeNode.VisitDepthChildFirst(sizer, nil)
err = previousTreeNode.VisitDepthChildFirst(sizer, nil)
if err != nil {
logrus.Errorf("unable to propagate whiteout dir: %+v", err)
}
}

} else {
Expand All @@ -80,7 +83,10 @@ func Efficiency(trees []*FileTree) (float64, EfficiencySlice) {
}
for idx, tree := range trees {
currentTree = idx
tree.VisitDepthChildFirst(visitor, visitEvaluator)
err := tree.VisitDepthChildFirst(visitor, visitEvaluator)
if err != nil {
logrus.Errorf("unable to propagate ref tree: %+v", err)
}
}

// calculate the score
Expand Down
7 changes: 5 additions & 2 deletions filetree/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package filetree
import (
"archive/tar"
"fmt"
"github.com/sirupsen/logrus"
"sort"
"strings"

Expand Down Expand Up @@ -149,7 +150,10 @@ func (node *FileNode) MetadataString() string {
return nil
}

node.VisitDepthChildFirst(sizer, nil)
err := node.VisitDepthChildFirst(sizer, nil)
if err != nil {
logrus.Errorf("unable to propagate node for metadata: %+v", err)
}
}

size := humanize.Bytes(uint64(sizeBytes))
Expand Down Expand Up @@ -258,7 +262,6 @@ func (node *FileNode) deriveDiffType(diffType DiffType) error {
myDiffType := diffType
for _, v := range node.Children {
myDiffType = myDiffType.merge(v.Data.DiffType)

}

return node.AssignDiffType(myDiffType)
Expand Down
70 changes: 39 additions & 31 deletions filetree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,15 @@ func (tree *FileTree) Copy() *FileTree {
newTree.Root = tree.Root.Copy(newTree.Root)

// update the tree pointers
newTree.VisitDepthChildFirst(func(node *FileNode) error {
err := newTree.VisitDepthChildFirst(func(node *FileNode) error {
node.Tree = newTree
return nil
}, nil)

if err != nil {
logrus.Errorf("unable to propagate tree on copy(): %+v", err)
}

return newTree
}

Expand Down Expand Up @@ -239,13 +243,14 @@ func (tree *FileTree) RemovePath(path string) error {
}

type compareMark struct {
node *FileNode
lowerNode *FileNode
upperNode *FileNode
tentative DiffType
final DiffType
}

// Compare marks the FileNodes in the owning (lower) tree with DiffType annotations when compared to the given (upper) tree.
func (tree *FileTree) Compare(upper *FileTree) error {
// CompareAndMark marks the FileNodes in the owning (lower) tree with DiffType annotations when compared to the given (upper) tree.
func (tree *FileTree) CompareAndMark(upper *FileTree) error {
// always compare relative to the original, unaltered tree.
originalTree := tree

Expand All @@ -257,28 +262,30 @@ func (tree *FileTree) Compare(upper *FileTree) error {
if err != nil {
return fmt.Errorf("cannot remove upperNode %s: %v", upperNode.Path(), err.Error())
}
} else {
// note: since we are not comparing against the original tree (copying the tree is expensive) we may mark the parent
// of an added node incorrectly as modified. This will be corrected later.
originalLowerNode, _ := originalTree.GetNode(upperNode.Path())

if originalLowerNode == nil {
_, newNodes, err := tree.AddPath(upperNode.Path(), upperNode.Data.FileInfo)
if err != nil {
return fmt.Errorf("cannot add new upperNode %s: %v", upperNode.Path(), err.Error())
}
for idx := len(newNodes) - 1; idx >= 0; idx-- {
newNode := newNodes[idx]
modifications = append(modifications, compareMark{node: newNode, tentative: -1, final: Added})
}

} else {
// check the tree for comparison markings
lowerNode, _ := tree.GetNode(upperNode.Path())
diffType := lowerNode.compare(upperNode)
modifications = append(modifications, compareMark{node: lowerNode, tentative: diffType, final: -1})
return nil
}

// note: since we are not comparing against the original tree (copying the tree is expensive) we may mark the parent
// of an added node incorrectly as modified. This will be corrected later.
originalLowerNode, _ := originalTree.GetNode(upperNode.Path())

if originalLowerNode == nil {
_, newNodes, err := tree.AddPath(upperNode.Path(), upperNode.Data.FileInfo)
if err != nil {
return fmt.Errorf("cannot add new upperNode %s: %v", upperNode.Path(), err.Error())
}
for idx := len(newNodes) - 1; idx >= 0; idx-- {
newNode := newNodes[idx]
modifications = append(modifications, compareMark{lowerNode: newNode, upperNode: upperNode, tentative: -1, final: Added})
}
return nil
}

// the file exists in the lower layer
lowerNode, _ := tree.GetNode(upperNode.Path())
diffType := lowerNode.compare(upperNode)
modifications = append(modifications, compareMark{lowerNode: lowerNode, upperNode: upperNode, tentative: diffType, final: -1})

return nil
}
// we must visit from the leaves upwards to ensure that diff types can be derived from and assigned to children
Expand All @@ -287,15 +294,16 @@ func (tree *FileTree) Compare(upper *FileTree) error {
return err
}

// take note of the comparison results on each note in the owning tree
// take note of the comparison results on each note in the owning tree.
for _, pair := range modifications {
if pair.final > 0 {
pair.node.AssignDiffType(pair.final)
} else {
if pair.node.Data.DiffType == Unchanged {
pair.node.deriveDiffType(pair.tentative)
}
pair.lowerNode.AssignDiffType(pair.final)
} else if pair.lowerNode.Data.DiffType == Unchanged {
pair.lowerNode.deriveDiffType(pair.tentative)
}

// persist the upper's payload on the owning tree
pair.lowerNode.Data.FileInfo = *pair.upperNode.Data.FileInfo.Copy()
}
return nil
}
Expand All @@ -316,7 +324,7 @@ func StackTreeRange(trees []*FileTree, start, stop int) *FileTree {
for idx := start; idx <= stop; idx++ {
err := tree.Stack(trees[idx])
if err != nil {
logrus.Debug("could not stack tree range:", err)
logrus.Errorf("could not stack tree range: %v", err)
}
}
return tree
Expand Down
8 changes: 4 additions & 4 deletions filetree/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ func TestCompareWithNoChanges(t *testing.T) {
lowerTree.AddPath(value, fakeData)
upperTree.AddPath(value, fakeData)
}
lowerTree.Compare(upperTree)
lowerTree.CompareAndMark(upperTree)
asserter := func(n *FileNode) error {
if n.Path() == "/" {
return nil
Expand Down Expand Up @@ -307,7 +307,7 @@ func TestCompareWithAdds(t *testing.T) {
}

failedAssertions := []error{}
err := lowerTree.Compare(upperTree)
err := lowerTree.CompareAndMark(upperTree)
if err != nil {
t.Errorf("Expected tree compare to have no errors, got: %v", err)
}
Expand Down Expand Up @@ -403,7 +403,7 @@ func TestCompareWithChanges(t *testing.T) {

changedPaths = append(changedPaths, chownPath)

lowerTree.Compare(upperTree)
lowerTree.CompareAndMark(upperTree)
failedAssertions := []error{}
asserter := func(n *FileNode) error {
p := n.Path()
Expand Down Expand Up @@ -458,7 +458,7 @@ func TestCompareWithRemoves(t *testing.T) {
upperTree.AddPath(value, fakeData)
}

lowerTree.Compare(upperTree)
lowerTree.CompareAndMark(upperTree)
failedAssertions := []error{}
asserter := func(n *FileNode) error {
p := n.Path()
Expand Down
19 changes: 16 additions & 3 deletions ui/filetreeview.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ func (view *FileTreeView) setTreeByLayer(bottomTreeStart, bottomTreeStop, topTre
}
return nil
}
view.ModelTree.VisitDepthChildFirst(visitor, nil)
err := view.ModelTree.VisitDepthChildFirst(visitor, nil)
if err != nil {
logrus.Errorf("unable to propagate layer tree: %+v", err)
}

view.resetCursor()

Expand Down Expand Up @@ -504,12 +507,13 @@ func (view *FileTreeView) Update() error {
regex := filterRegex()

// keep the view selection in parity with the current DiffType selection
view.ModelTree.VisitDepthChildFirst(func(node *filetree.FileNode) error {
err := view.ModelTree.VisitDepthChildFirst(func(node *filetree.FileNode) error {
node.Data.ViewInfo.Hidden = view.HiddenDiffTypes[node.Data.DiffType]
visibleChild := false
for _, child := range node.Children {
if !child.Data.ViewInfo.Hidden {
visibleChild = true
node.Data.ViewInfo.Hidden = false
}
}
if regex != nil && !visibleChild {
Expand All @@ -519,14 +523,23 @@ func (view *FileTreeView) Update() error {
return nil
}, nil)

if err != nil {
logrus.Errorf("unable to propagate model tree: %+v", err)
}

// make a new tree with only visible nodes
view.ViewTree = view.ModelTree.Copy()
view.ViewTree.VisitDepthParentFirst(func(node *filetree.FileNode) error {
err = view.ViewTree.VisitDepthParentFirst(func(node *filetree.FileNode) error {
if node.Data.ViewInfo.Hidden {
view.ViewTree.RemovePath(node.Path())
}
return nil
}, nil)

if err != nil {
logrus.Errorf("unable to propagate view tree: %+v", err)
}

return nil
}

Expand Down