Count occurrences of each leaf path
We want to be able to know whether the same file appears many times in the layers of the docker image, because a file that appears many times may represent a real inefficiency in the dockerfile.
This commit is contained in:
parent
bbe7d436ce
commit
de7c3a759a
@ -187,7 +187,7 @@ func (tree *FileTree) Compare(upper *FileTree) error {
|
||||
if upperNode.IsWhiteout() {
|
||||
err := tree.MarkRemoved(upperNode.Path())
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot remove upperNode %s: %v", upperNode.Path(), err.Error())
|
||||
return fmt.Errorf("cannot remove upperNode %s: %v", upperNode.Path(), err.Error())
|
||||
}
|
||||
} else {
|
||||
lowerNode, _ := tree.GetNode(upperNode.Path())
|
||||
@ -195,7 +195,7 @@ func (tree *FileTree) Compare(upper *FileTree) error {
|
||||
newNode, err := tree.AddPath(upperNode.Path(), upperNode.Data.FileInfo)
|
||||
// fmt.Printf("added new upperNode at %s\n", newNode.Path())
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot add new upperNode %s: %v", upperNode.Path(), err.Error())
|
||||
return fmt.Errorf("cannot add new upperNode %s: %v", upperNode.Path(), err.Error())
|
||||
}
|
||||
newNode.AssignDiffType(Added)
|
||||
} else {
|
||||
@ -224,3 +224,20 @@ func StackRange(trees []*FileTree, start, stop int) *FileTree {
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
// EfficiencyMap creates a map[string]int showing how often each int
|
||||
// appears in the
|
||||
func EfficiencyMap(trees []*FileTree) map[string]int {
|
||||
result := make(map[string]int)
|
||||
visitor := func(node *FileNode) error {
|
||||
result[node.Path()]++
|
||||
return nil
|
||||
}
|
||||
visitEvaluator := func(node *FileNode) bool {
|
||||
return node.IsLeaf()
|
||||
}
|
||||
for _, tree := range trees {
|
||||
tree.VisitDepthChildFirst(visitor, visitEvaluator)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package filetree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -29,7 +30,7 @@ func TestPrintTree(t *testing.T) {
|
||||
two.AddChild("forth, one level down...", FileInfo{})
|
||||
|
||||
expected :=
|
||||
`├── first node!
|
||||
`├── first node!
|
||||
├── second node!
|
||||
│ └── forth, one level down...
|
||||
└── third node!
|
||||
@ -52,7 +53,7 @@ func TestAddPath(t *testing.T) {
|
||||
tree.AddPath("/tmp/nonsense", FileInfo{})
|
||||
|
||||
expected :=
|
||||
`├── etc
|
||||
`├── etc
|
||||
│ └── nginx
|
||||
│ ├── nginx.conf
|
||||
│ └── public
|
||||
@ -84,7 +85,7 @@ func TestRemovePath(t *testing.T) {
|
||||
tree.RemovePath("/tmp")
|
||||
|
||||
expected :=
|
||||
`├── etc
|
||||
`├── etc
|
||||
│ └── nginx
|
||||
│ ├── nginx.conf
|
||||
│ └── public
|
||||
@ -130,7 +131,7 @@ func TestStack(t *testing.T) {
|
||||
}
|
||||
|
||||
expected :=
|
||||
`├── etc
|
||||
`├── etc
|
||||
│ └── nginx
|
||||
│ ├── nginx.conf
|
||||
│ └── public
|
||||
@ -169,7 +170,7 @@ func TestCopy(t *testing.T) {
|
||||
tree.RemovePath("/tmp")
|
||||
|
||||
expected :=
|
||||
`├── etc
|
||||
`├── etc
|
||||
│ └── nginx
|
||||
│ ├── nginx.conf
|
||||
│ └── public
|
||||
@ -249,11 +250,11 @@ func TestCompareWithAdds(t *testing.T) {
|
||||
p := n.Path()
|
||||
if p == "/" {
|
||||
return nil
|
||||
} else if stringInSlice(p,[]string{"/usr/bin/bash"}) {
|
||||
} else if stringInSlice(p, []string{"/usr/bin/bash"}) {
|
||||
if err := AssertDiffType(n, Added); err != nil {
|
||||
failedAssertions = append(failedAssertions, err)
|
||||
}
|
||||
} else if stringInSlice(p,[]string{"/usr/bin", "/usr"}) {
|
||||
} else if stringInSlice(p, []string{"/usr/bin", "/usr"}) {
|
||||
if err := AssertDiffType(n, Changed); err != nil {
|
||||
failedAssertions = append(failedAssertions, err)
|
||||
}
|
||||
@ -296,7 +297,6 @@ func TestCompareWithChanges(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
lowerTree.Compare(upperTree)
|
||||
failedAssertions := []error{}
|
||||
asserter := func(n *FileNode) error {
|
||||
@ -328,7 +328,6 @@ func TestCompareWithChanges(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestCompareWithRemoves(t *testing.T) {
|
||||
lowerTree := NewFileTree()
|
||||
upperTree := NewFileTree()
|
||||
@ -359,11 +358,11 @@ func TestCompareWithRemoves(t *testing.T) {
|
||||
p := n.Path()
|
||||
if p == "/" {
|
||||
return nil
|
||||
} else if stringInSlice(p,[]string{"/etc", "/usr/bin", "/etc/hosts", "/etc/sudoers", "/root/example/some1", "/root/example/some2", "/root/example"}) {
|
||||
} else if stringInSlice(p, []string{"/etc", "/usr/bin", "/etc/hosts", "/etc/sudoers", "/root/example/some1", "/root/example/some2", "/root/example"}) {
|
||||
if err := AssertDiffType(n, Removed); err != nil {
|
||||
failedAssertions = append(failedAssertions, err)
|
||||
}
|
||||
} else if stringInSlice(p,[]string{"/usr", "/root"}) {
|
||||
} else if stringInSlice(p, []string{"/usr", "/root"}) {
|
||||
if err := AssertDiffType(n, Changed); err != nil {
|
||||
failedAssertions = append(failedAssertions, err)
|
||||
}
|
||||
@ -426,7 +425,6 @@ func TestStackRange(t *testing.T) {
|
||||
StackRange(trees, 0, 2)
|
||||
}
|
||||
|
||||
|
||||
func TestRemoveOnIterate(t *testing.T) {
|
||||
|
||||
tree := NewFileTree()
|
||||
@ -452,7 +450,7 @@ func TestRemoveOnIterate(t *testing.T) {
|
||||
}, nil)
|
||||
|
||||
expected :=
|
||||
`└── usr
|
||||
`└── usr
|
||||
├── bin
|
||||
└── something
|
||||
`
|
||||
@ -463,3 +461,20 @@ func TestRemoveOnIterate(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestEfficencyMap(t *testing.T) {
|
||||
trees := make([]*FileTree, 3)
|
||||
for ix, _ := range trees {
|
||||
tree := NewFileTree()
|
||||
tree.AddPath("/etc/nginx/nginx.conf", FileInfo{})
|
||||
tree.AddPath("/etc/nginx/public", FileInfo{})
|
||||
trees[ix] = tree
|
||||
}
|
||||
var expectedMap = map[string]int{
|
||||
"/etc/nginx/nginx.conf": 3,
|
||||
"/etc/nginx/public": 3,
|
||||
}
|
||||
actualMap := EfficiencyMap(trees)
|
||||
if !reflect.DeepEqual(expectedMap, actualMap) {
|
||||
t.Fatalf("Expected %v but go %v", expectedMap, actualMap)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user