Merge pull request #252 from wagoodman/fix-log-and-tar-paths

Fix log and relative paths
This commit is contained in:
Alex Goodman 2019-11-20 15:15:38 -08:00 committed by GitHub
commit 35db1ec914
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 346 additions and 145 deletions

View File

@ -121,6 +121,7 @@ func initLogging() {
if viper.GetBool("log.enabled") {
logFileObj, err = os.OpenFile(viper.GetString("log.path"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
log.SetOutput(logFileObj)
} else {
log.SetOutput(ioutil.Discard)
}
@ -139,7 +140,6 @@ func initLogging() {
}
log.SetLevel(level)
log.SetOutput(logFileObj)
log.Debug("Starting Dive...")
}

View File

@ -1,93 +0,0 @@
package filetree
import (
"github.com/sirupsen/logrus"
)
type TreeCacheKey struct {
bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int
}
type TreeCache struct {
refTrees []*FileTree
cache map[TreeCacheKey]*FileTree
}
func (cache *TreeCache) Get(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int) (*FileTree, error) {
key := TreeCacheKey{bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop}
if value, exists := cache.cache[key]; exists {
return value, nil
}
value, err := cache.buildTree(key)
if err != nil {
return nil, err
}
cache.cache[key] = value
return value, nil
}
func (cache *TreeCache) buildTree(key TreeCacheKey) (*FileTree, error) {
newTree, err := StackTreeRange(cache.refTrees, key.bottomTreeStart, key.bottomTreeStop)
if err != nil {
return nil, err
}
for idx := key.topTreeStart; idx <= key.topTreeStop; idx++ {
err := newTree.CompareAndMark(cache.refTrees[idx])
if err != nil {
logrus.Errorf("unable to build tree: %+v", err)
return nil, err
}
}
return newTree, nil
}
func (cache *TreeCache) Build() error {
var bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int
// case 1: layer compare (top tree SIZE is fixed (BUT floats forward), Bottom tree SIZE changes)
for selectIdx := 0; selectIdx < len(cache.refTrees); selectIdx++ {
bottomTreeStart = 0
topTreeStop = selectIdx
if selectIdx == 0 {
bottomTreeStop = selectIdx
topTreeStart = selectIdx
} else {
bottomTreeStop = selectIdx - 1
topTreeStart = selectIdx
}
_, err := cache.Get(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop)
if err != nil {
return err
}
}
// case 2: aggregated compare (bottom tree is ENTIRELY fixed, top tree SIZE changes)
for selectIdx := 0; selectIdx < len(cache.refTrees); selectIdx++ {
bottomTreeStart = 0
topTreeStop = selectIdx
if selectIdx == 0 {
bottomTreeStop = selectIdx
topTreeStart = selectIdx
} else {
bottomTreeStop = 0
topTreeStart = 1
}
_, err := cache.Get(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop)
if err != nil {
return err
}
}
return nil
}
func NewFileTreeCache(refTrees []*FileTree) TreeCache {
return TreeCache{
refTrees: refTrees,
cache: make(map[TreeCacheKey]*FileTree),
}
}

175
dive/filetree/comparer.go Normal file
View File

@ -0,0 +1,175 @@
package filetree
import (
"fmt"
"github.com/sirupsen/logrus"
)
type TreeIndexKey struct {
bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int
}
func NewTreeIndexKey(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int) TreeIndexKey {
return TreeIndexKey{
bottomTreeStart: bottomTreeStart,
bottomTreeStop: bottomTreeStop,
topTreeStart: topTreeStart,
topTreeStop: topTreeStop,
}
}
func (index TreeIndexKey) String() string {
if index.bottomTreeStart == index.bottomTreeStop && index.topTreeStart == index.topTreeStop {
return fmt.Sprintf("Index(%d:%d)", index.bottomTreeStart, index.topTreeStart)
} else if index.bottomTreeStart == index.bottomTreeStop {
return fmt.Sprintf("Index(%d:%d-%d)", index.bottomTreeStart, index.topTreeStart, index.topTreeStop)
} else if index.topTreeStart == index.topTreeStop {
return fmt.Sprintf("Index(%d-%d:%d)", index.bottomTreeStart, index.bottomTreeStop, index.topTreeStart)
}
return fmt.Sprintf("Index(%d-%d:%d-%d)", index.bottomTreeStart, index.bottomTreeStop, index.topTreeStart, index.topTreeStop)
}
type Comparer struct {
refTrees []*FileTree
trees map[TreeIndexKey]*FileTree
pathErrors map[TreeIndexKey][]PathError
}
func NewComparer(refTrees []*FileTree) Comparer {
return Comparer{
refTrees: refTrees,
trees: make(map[TreeIndexKey]*FileTree),
pathErrors: make(map[TreeIndexKey][]PathError),
}
}
func (cmp *Comparer) GetPathErrors(key TreeIndexKey) ([]PathError, error) {
_, pathErrors, err := cmp.get(key)
if err != nil {
return nil, err
}
return pathErrors, nil
}
func (cmp *Comparer) GetTree(key TreeIndexKey) (*FileTree, error) {
//func (cmp *Comparer) GetTree(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int) (*FileTree, []PathError, error) {
//key := TreeIndexKey{bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop}
if value, exists := cmp.trees[key]; exists {
return value, nil
}
value, pathErrors, err := cmp.get(key)
if err != nil {
return nil, err
}
cmp.trees[key] = value
cmp.pathErrors[key] = pathErrors
return value, nil
}
func (cmp *Comparer) get(key TreeIndexKey) (*FileTree, []PathError, error) {
newTree, pathErrors, err := StackTreeRange(cmp.refTrees, key.bottomTreeStart, key.bottomTreeStop)
if err != nil {
return nil, nil, err
}
for idx := key.topTreeStart; idx <= key.topTreeStop; idx++ {
markPathErrors, err := newTree.CompareAndMark(cmp.refTrees[idx])
pathErrors = append(pathErrors, markPathErrors...)
if err != nil {
logrus.Errorf("error while building tree: %+v", err)
return nil, nil, err
}
}
return newTree, pathErrors, nil
}
// case 1: layer compare (top tree SIZE is fixed (BUT floats forward), Bottom tree SIZE changes)
func (cmp *Comparer) NaturalIndexes() <-chan TreeIndexKey {
indexes := make(chan TreeIndexKey)
go func() {
defer close(indexes)
var bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int
for selectIdx := 0; selectIdx < len(cmp.refTrees); selectIdx++ {
bottomTreeStart = 0
topTreeStop = selectIdx
if selectIdx == 0 {
bottomTreeStop = selectIdx
topTreeStart = selectIdx
} else {
bottomTreeStop = selectIdx - 1
topTreeStart = selectIdx
}
indexes <- TreeIndexKey{
bottomTreeStart: bottomTreeStart,
bottomTreeStop: bottomTreeStop,
topTreeStart: topTreeStart,
topTreeStop: topTreeStop,
}
}
}()
return indexes
}
// case 2: aggregated compare (bottom tree is ENTIRELY fixed, top tree SIZE changes)
func (cmp *Comparer) AggregatedIndexes() <-chan TreeIndexKey {
indexes := make(chan TreeIndexKey)
go func() {
defer close(indexes)
var bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int
for selectIdx := 0; selectIdx < len(cmp.refTrees); selectIdx++ {
bottomTreeStart = 0
topTreeStop = selectIdx
if selectIdx == 0 {
bottomTreeStop = selectIdx
topTreeStart = selectIdx
} else {
bottomTreeStop = 0
topTreeStart = 1
}
indexes <- TreeIndexKey{
bottomTreeStart: bottomTreeStart,
bottomTreeStop: bottomTreeStop,
topTreeStart: topTreeStart,
topTreeStop: topTreeStop,
}
}
}()
return indexes
}
func (cmp *Comparer) BuildCache() (errors []error) {
for index := range cmp.NaturalIndexes() {
pathError, _ := cmp.GetPathErrors(index)
if len(pathError) > 0 {
for _, path := range pathError {
errors = append(errors, fmt.Errorf("path error at layer index %s: %s", index, path))
}
}
_, err := cmp.GetTree(index)
if err != nil {
errors = append(errors, err)
return errors
}
}
for index := range cmp.AggregatedIndexes() {
_, err := cmp.GetTree(index)
if err != nil {
errors = append(errors, err)
return errors
}
}
return errors
}

View File

@ -62,7 +62,12 @@ func Efficiency(trees []*FileTree) (float64, EfficiencySlice) {
sizeBytes += curNode.Data.FileInfo.Size
return nil
}
stackedTree, err := StackTreeRange(trees, 0, currentTree-1)
stackedTree, failedPaths, err := StackTreeRange(trees, 0, currentTree-1)
if len(failedPaths) > 0 {
for _, path := range failedPaths {
logrus.Errorf(path.String())
}
}
if err != nil {
logrus.Errorf("unable to stack tree range: %+v", err)
return err

View File

@ -2,6 +2,7 @@ package filetree
import (
"fmt"
"path"
"sort"
"strings"
@ -204,22 +205,23 @@ func (tree *FileTree) VisitDepthParentFirst(visitor Visitor, evaluator VisitEval
}
// Stack takes two trees and combines them together. This is done by "stacking" the given tree on top of the owning tree.
func (tree *FileTree) Stack(upper *FileTree) error {
func (tree *FileTree) Stack(upper *FileTree) (failed []PathError, stackErr error) {
graft := func(node *FileNode) error {
if node.IsWhiteout() {
err := tree.RemovePath(node.Path())
if err != nil {
return fmt.Errorf("cannot remove node %s: %v", node.Path(), err.Error())
failed = append(failed, NewPathError(node.Path(), ActionAdd, err))
}
} else {
newNode, _, err := tree.AddPath(node.Path(), node.Data.FileInfo)
_, _, err := tree.AddPath(node.Path(), node.Data.FileInfo)
if err != nil {
return fmt.Errorf("cannot add node %s: %v", newNode.Path(), err.Error())
failed = append(failed, NewPathError(node.Path(), ActionRemove, err))
}
}
return nil
}
return upper.VisitDepthChildFirst(graft, nil)
stackErr = upper.VisitDepthChildFirst(graft, nil)
return failed, stackErr
}
// GetNode fetches a single node when given a slash-delimited string from root ('/') to the desired node (e.g. '/a/node/path')
@ -239,8 +241,12 @@ func (tree *FileTree) GetNode(path string) (*FileNode, error) {
}
// AddPath adds a new node to the tree with the given payload
func (tree *FileTree) AddPath(path string, data FileInfo) (*FileNode, []*FileNode, error) {
nodeNames := strings.Split(strings.Trim(path, "/"), "/")
func (tree *FileTree) AddPath(filepath string, data FileInfo) (*FileNode, []*FileNode, error) {
filepath = path.Clean(filepath)
if filepath == "." {
return nil, nil, fmt.Errorf("cannot add relative path '%s'", filepath)
}
nodeNames := strings.Split(strings.Trim(filepath, "/"), "/")
node := tree.Root
addedNodes := make([]*FileNode, 0)
for idx, name := range nodeNames {
@ -263,7 +269,7 @@ func (tree *FileTree) AddPath(path string, data FileInfo) (*FileNode, []*FileNod
if node == nil {
// the child could not be added
return node, addedNodes, fmt.Errorf(fmt.Sprintf("could not add child node: '%s' (path:'%s')", name, path))
return node, addedNodes, fmt.Errorf(fmt.Sprintf("could not add child node: '%s' (path:'%s')", name, filepath))
}
}
@ -293,17 +299,18 @@ type compareMark struct {
}
// 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 {
func (tree *FileTree) CompareAndMark(upper *FileTree) ([]PathError, error) {
// always compare relative to the original, unaltered tree.
originalTree := tree
modifications := make([]compareMark, 0)
failed := make([]PathError, 0)
graft := func(upperNode *FileNode) error {
if upperNode.IsWhiteout() {
err := tree.markRemoved(upperNode.Path())
if err != nil {
return fmt.Errorf("cannot remove upperNode %s: %v", upperNode.Path(), err.Error())
failed = append(failed, NewPathError(upperNode.Path(), ActionRemove, err))
}
return nil
}
@ -315,7 +322,8 @@ func (tree *FileTree) CompareAndMark(upper *FileTree) error {
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())
failed = append(failed, NewPathError(upperNode.Path(), ActionAdd, err))
return nil
}
for idx := len(newNodes) - 1; idx >= 0; idx-- {
newNode := newNodes[idx]
@ -334,7 +342,7 @@ func (tree *FileTree) CompareAndMark(upper *FileTree) error {
// we must visit from the leaves upwards to ensure that diff types can be derived from and assigned to children
err := upper.VisitDepthChildFirst(graft, nil)
if err != nil {
return err
return failed, err
}
// take note of the comparison results on each note in the owning tree.
@ -342,19 +350,19 @@ func (tree *FileTree) CompareAndMark(upper *FileTree) error {
if pair.final > 0 {
err = pair.lowerNode.AssignDiffType(pair.final)
if err != nil {
return err
return failed, err
}
} else if pair.lowerNode.Data.DiffType == Unmodified {
err = pair.lowerNode.deriveDiffType(pair.tentative)
if err != nil {
return err
return failed, err
}
}
// persist the upper's payload on the owning tree
pair.lowerNode.Data.FileInfo = *pair.upperNode.Data.FileInfo.Copy()
}
return nil
return failed, nil
}
// markRemoved annotates the FileNode at the given path as Removed.
@ -367,15 +375,18 @@ func (tree *FileTree) markRemoved(path string) error {
}
// StackTreeRange combines an array of trees into a single tree
func StackTreeRange(trees []*FileTree, start, stop int) (*FileTree, error) {
func StackTreeRange(trees []*FileTree, start, stop int) (*FileTree, []PathError, error) {
errors := make([]PathError, 0)
tree := trees[0].Copy()
for idx := start; idx <= stop; idx++ {
err := tree.Stack(trees[idx])
failedPaths, err := tree.Stack(trees[idx])
if len(failedPaths) > 0 {
errors = append(errors, failedPaths...)
}
if err != nil {
logrus.Errorf("could not stack tree range: %v", err)
return nil, err
return nil, nil, err
}
}
return tree, nil
return tree, errors, nil
}

View File

@ -125,6 +125,40 @@ func TestStringBetween(t *testing.T) {
}
func TestRejectPurelyRelativePath(t *testing.T) {
tree := NewFileTree()
_, _, err := tree.AddPath("./etc/nginx/nginx.conf", FileInfo{})
if err != nil {
t.Errorf("could not setup test: %v", err)
}
_, _, err = tree.AddPath("./", FileInfo{})
if err == nil {
t.Errorf("expected to reject relative path, but did not")
}
}
func TestAddRelativePath(t *testing.T) {
tree := NewFileTree()
_, _, err := tree.AddPath("./etc/nginx/nginx.conf", FileInfo{})
if err != nil {
t.Errorf("could not setup test: %v", err)
}
expected :=
` etc
nginx
nginx.conf
`
actual := tree.String(false)
if expected != actual {
t.Errorf("Expected tree string:\n--->%s<---\nGot:\n--->%s<---", expected, actual)
}
}
func TestAddPath(t *testing.T) {
tree := NewFileTree()
_, _, err := tree.AddPath("/etc/nginx/nginx.conf", FileInfo{})
@ -307,12 +341,16 @@ func TestStack(t *testing.T) {
t.Errorf("expected no node on whiteout file add, but got %v", node)
}
err = tree1.Stack(tree2)
failedPaths, err := tree1.Stack(tree2)
if err != nil {
t.Errorf("Could not stack refTrees: %v", err)
}
if len(failedPaths) > 0 {
t.Errorf("expected no filepath errors, got %d", len(failedPaths))
}
expected :=
` etc
nginx
@ -415,10 +453,13 @@ func TestCompareWithNoChanges(t *testing.T) {
t.Errorf("could not setup test: %v", err)
}
}
err := lowerTree.CompareAndMark(upperTree)
failedPaths, err := lowerTree.CompareAndMark(upperTree)
if err != nil {
t.Errorf("could not setup test: %v", err)
}
if len(failedPaths) > 0 {
t.Errorf("expected no filepath errors, got %d", len(failedPaths))
}
asserter := func(n *FileNode) error {
if n.Path() == "/" {
return nil
@ -463,10 +504,13 @@ func TestCompareWithAdds(t *testing.T) {
}
failedAssertions := []error{}
err := lowerTree.CompareAndMark(upperTree)
failedPaths, err := lowerTree.CompareAndMark(upperTree)
if err != nil {
t.Errorf("Expected tree compare to have no errors, got: %v", err)
}
if len(failedPaths) > 0 {
t.Errorf("expected no filepath errors, got %d", len(failedPaths))
}
asserter := func(n *FileNode) error {
p := n.Path()
@ -577,11 +621,13 @@ func TestCompareWithChanges(t *testing.T) {
changedPaths = append(changedPaths, chownPath)
err = lowerTree.CompareAndMark(upperTree)
failedPaths, err := lowerTree.CompareAndMark(upperTree)
if err != nil {
t.Errorf("unable to compare and mark: %+v", err)
}
if len(failedPaths) > 0 {
t.Errorf("expected no filepath errors, got %d", len(failedPaths))
}
failedAssertions := []error{}
asserter := func(n *FileNode) error {
p := n.Path()
@ -642,10 +688,13 @@ func TestCompareWithRemoves(t *testing.T) {
}
}
err := lowerTree.CompareAndMark(upperTree)
failedPaths, err := lowerTree.CompareAndMark(upperTree)
if err != nil {
t.Errorf("could not setup test: %v", err)
}
if len(failedPaths) > 0 {
t.Errorf("expected no filepath errors, got %d", len(failedPaths))
}
failedAssertions := []error{}
asserter := func(n *FileNode) error {
p := n.Path()
@ -745,7 +794,10 @@ func TestStackRange(t *testing.T) {
}
}
trees := []*FileTree{lowerTree, upperTree, tree}
_, err = StackTreeRange(trees, 0, 2)
_, failedPaths, err := StackTreeRange(trees, 0, 2)
if len(failedPaths) > 0 {
t.Errorf("expected no filepath errors, got %d", len(failedPaths))
}
if err != nil {
t.Fatal(err)
}

View File

@ -0,0 +1,39 @@
package filetree
import "fmt"
const (
ActionAdd FileAction = iota
ActionRemove
)
type FileAction int
func (fa FileAction) String() string {
switch fa {
case ActionAdd:
return "add"
case ActionRemove:
return "remove"
default:
return "<unknown file action>"
}
}
type PathError struct {
Path string
Action FileAction
Err error
}
func NewPathError(path string, action FileAction, err error) PathError {
return PathError{
Path: path,
Action: action,
Err: err,
}
}
func (pe PathError) String() string {
return fmt.Sprintf("unable to %s '%s': %+v", pe.Action.String(), pe.Path, pe.Err)
}

View File

@ -8,6 +8,7 @@ import (
"io"
"io/ioutil"
"os"
"path"
"strings"
)
@ -119,7 +120,11 @@ func getFileList(tarReader *tar.Reader) ([]filetree.FileInfo, error) {
return nil, err
}
name := header.Name
// always ensure relative path notations are not parsed as part of the filename
name := path.Clean(header.Name)
if name == "." {
continue
}
switch header.Typeflag {
case tar.TypeXGlobalHeader:

View File

@ -87,10 +87,13 @@ func run(enableUi bool, options Options, imageResolver image.Resolver, events ev
} else {
events.message(utils.TitleFormat("Building cache..."))
cache := filetree.NewFileTreeCache(analysis.RefTrees)
err := cache.Build()
if err != nil {
events.exitWithErrorMessage("cannot build cache tree", err)
treeStack := filetree.NewComparer(analysis.RefTrees)
errors := treeStack.BuildCache()
if errors != nil {
for _, err := range errors {
events.message(" " + err.Error())
}
events.exitWithError(fmt.Errorf("file tree has path errors"))
return
}
@ -102,7 +105,7 @@ func run(enableUi bool, options Options, imageResolver image.Resolver, events ev
// enough sleep will prevent this behavior (todo: remove this hack)
time.Sleep(100 * time.Millisecond)
err = ui.Run(analysis, cache)
err = ui.Run(analysis, treeStack)
if err != nil {
events.exitWithError(err)
return

View File

@ -24,7 +24,7 @@ var (
appSingleton *app
)
func newApp(gui *gocui.Gui, analysis *image.AnalysisResult, cache filetree.TreeCache) (*app, error) {
func newApp(gui *gocui.Gui, analysis *image.AnalysisResult, cache filetree.Comparer) (*app, error) {
var err error
once.Do(func() {
var theControls *Controller
@ -118,7 +118,7 @@ func (a *app) quit() error {
}
// Run is the UI entrypoint.
func Run(analysis *image.AnalysisResult, cache filetree.TreeCache) error {
func Run(analysis *image.AnalysisResult, treeStack filetree.Comparer) error {
var err error
g, err := gocui.NewGui(gocui.OutputNormal)
@ -127,7 +127,7 @@ func Run(analysis *image.AnalysisResult, cache filetree.TreeCache) error {
}
defer g.Close()
_, err = newApp(g, analysis, cache)
_, err = newApp(g, analysis, treeStack)
if err != nil {
return err
}

View File

@ -20,7 +20,7 @@ type Controller struct {
lookup map[string]view.Renderer
}
func NewCollection(g *gocui.Gui, analysis *image.AnalysisResult, cache filetree.TreeCache) (*Controller, error) {
func NewCollection(g *gocui.Gui, analysis *image.AnalysisResult, cache filetree.Comparer) (*Controller, error) {
var err error
controller := &Controller{
@ -34,10 +34,11 @@ func NewCollection(g *gocui.Gui, analysis *image.AnalysisResult, cache filetree.
}
controller.lookup[controller.Layer.Name()] = controller.Layer
treeStack, err := filetree.StackTreeRange(analysis.RefTrees, 0, 0)
if err != nil {
return nil, err
}
//treeStack, err := filetree.StackTreeRange(analysis.RefTrees, 0, 0)
//if err != nil {
// return nil, err
//}
treeStack := analysis.RefTrees[0]
controller.Tree, err = view.NewFileTreeView("filetree", g, treeStack, analysis.RefTrees, cache)
if err != nil {
return nil, err

View File

@ -41,7 +41,7 @@ type FileTree struct {
}
// NewFileTreeView creates a new view object attached the the global [gocui] screen object.
func NewFileTreeView(name string, gui *gocui.Gui, tree *filetree.FileTree, refTrees []*filetree.FileTree, cache filetree.TreeCache) (controller *FileTree, err error) {
func NewFileTreeView(name string, gui *gocui.Gui, tree *filetree.FileTree, refTrees []*filetree.FileTree, cache filetree.Comparer) (controller *FileTree, err error) {
controller = new(FileTree)
controller.listeners = make([]ViewOptionChangeListener, 0)

View File

@ -19,7 +19,7 @@ type FileTree struct {
ModelTree *filetree.FileTree
ViewTree *filetree.FileTree
RefTrees []*filetree.FileTree
cache filetree.TreeCache
cache filetree.Comparer
CollapseAll bool
ShowAttributes bool
@ -35,7 +35,7 @@ type FileTree struct {
}
// NewFileTreeViewModel creates a new view object attached the the global [gocui] screen object.
func NewFileTreeViewModel(tree *filetree.FileTree, refTrees []*filetree.FileTree, cache filetree.TreeCache) (treeViewModel *FileTree, err error) {
func NewFileTreeViewModel(tree *filetree.FileTree, refTrees []*filetree.FileTree, cache filetree.Comparer) (treeViewModel *FileTree, err error) {
treeViewModel = new(FileTree)
// populate main fields
@ -101,7 +101,7 @@ func (vm *FileTree) SetTreeByLayer(bottomTreeStart, bottomTreeStop, topTreeStart
if topTreeStop > len(vm.RefTrees)-1 {
return fmt.Errorf("invalid layer index given: %d of %d", topTreeStop, len(vm.RefTrees)-1)
}
newTree, err := vm.cache.Get(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop)
newTree, err := vm.cache.GetTree(filetree.NewTreeIndexKey(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop))
if err != nil {
logrus.Errorf("unable to fetch layer tree from cache: %+v", err)
return err

View File

@ -76,15 +76,18 @@ func assertTestData(t *testing.T, actualBytes []byte) {
func initializeTestViewModel(t *testing.T) *FileTree {
result := docker.TestAnalysisFromArchive(t, "../../../.data/test-docker-image.tar")
cache := filetree.NewFileTreeCache(result.RefTrees)
err := cache.Build()
if err != nil {
t.Fatalf("%s: unable to build cache: %+v", t.Name(), err)
cache := filetree.NewComparer(result.RefTrees)
errors := cache.BuildCache()
if len(errors) > 0 {
t.Fatalf("%s: unable to build cache: %d errors", t.Name(), len(errors))
}
format.Selected = color.New(color.ReverseVideo, color.Bold).SprintFunc()
treeStack, err := filetree.StackTreeRange(result.RefTrees, 0, 0)
treeStack, failedPaths, err := filetree.StackTreeRange(result.RefTrees, 0, 0)
if len(failedPaths) > 0 {
t.Errorf("expected no filepath errors, got %d", len(failedPaths))
}
if err != nil {
t.Fatalf("%s: unable to stack trees: %v", t.Name(), err)
}