diff options
author | Alex Goodman <wagoodman@users.noreply.github.com> | 2019-07-21 15:44:52 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-21 15:44:52 -0400 |
commit | 9384069d766826b2dc7fc56bcbc57d12cd2ff51e (patch) | |
tree | 767c0963758705c8dd169741aa72963cc023cf0f | |
parent | 57b1a3d5228872eba6589b0ae38ceccabd0f3344 (diff) | |
parent | ea0de60dc05cdb5b3fbf75655121b92c6ab93ec2 (diff) |
Merge branch 'master' into format-fixes
-rw-r--r-- | .dockerignore | 2 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | .gitlab-ci.yml | 26 | ||||
-rwxr-xr-x | .scripts/test-coverage.sh (renamed from .scripts/test.sh) | 0 | ||||
-rw-r--r-- | .travis.yml | 34 | ||||
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | cmd/analyze.go | 4 | ||||
-rw-r--r-- | cmd/root.go | 2 | ||||
-rw-r--r-- | filetree/cache.go | 2 | ||||
-rw-r--r-- | filetree/data.go | 25 | ||||
-rw-r--r-- | filetree/data_test.go | 16 | ||||
-rw-r--r-- | filetree/efficiency_test.go | 25 | ||||
-rw-r--r-- | filetree/node.go | 15 | ||||
-rw-r--r-- | filetree/node_test.go | 35 | ||||
-rw-r--r-- | filetree/tree.go | 19 | ||||
-rw-r--r-- | filetree/tree_test.go | 379 | ||||
-rw-r--r-- | go.mod | 12 | ||||
-rw-r--r-- | go.sum | 157 | ||||
-rw-r--r-- | image/docker_image.go | 10 | ||||
-rw-r--r-- | runtime/ci/evaluator.go | 5 | ||||
-rw-r--r-- | ui/details_controller.go | 23 | ||||
-rw-r--r-- | ui/filetree_controller.go | 55 | ||||
-rw-r--r-- | ui/filetree_viewmodel.go | 22 | ||||
-rw-r--r-- | ui/filetree_viewmodel_test.go | 25 | ||||
-rw-r--r-- | ui/filter_controller.go | 12 | ||||
-rw-r--r-- | ui/layer_controller.go | 32 | ||||
-rw-r--r-- | ui/status_controller.go | 11 | ||||
-rw-r--r-- | ui/ui.go | 52 |
29 files changed, 709 insertions, 314 deletions
diff --git a/.dockerignore b/.dockerignore index 402fbc0..52712ed 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,10 @@ /.git /.data +/.cover /dist /ui /utils /image /cmd /build +coverage.txt @@ -20,3 +20,4 @@ *.log /dist .cover +coverage.txt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..7ec9505 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,26 @@ +image: golang:1.12.5 + +cache: + paths: + - .cache + +variables: + GOPATH: $CI_PROJECT_DIR/.cache + +stages: + - setup + - validation + +setup: + stage: setup + script: + - mkdir -p .cache + - go get ./... + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.17.1 + +validation: + stage: validation + before_script: + - export PATH="$GOPATH/bin:$PATH" + script: + - make ci diff --git a/.scripts/test.sh b/.scripts/test-coverage.sh index 36db3a7..36db3a7 100755 --- a/.scripts/test.sh +++ b/.scripts/test-coverage.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 38c0be3..0000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -language: go - -os: - - linux - - linux-ppc64le - -go: -- '1.9.x' -- '1.10.x' -- '1.11.x' -- 'master' - -# Skip the install step. Don't `go get` dependencies. Only build with the -# code in vendor/ -install: true - -matrix: - # It's ok if our code fails on unstable development versions of Go. - allow_failures: - - go: master - # Don't wait for tip tests to finish. Mark the test run green if the - # tests pass on the stable versions of Go. - fast_finish: true - -notifications: - email: false - -before_script: -- go get -t ./... - -# Note: scripts always run to completion -script: -- make validate -- make test @@ -14,23 +14,26 @@ run-large: build build: go build -o build/$(BIN) -release: test validate +release: test-coverage validate ./.scripts/tag.sh goreleaser --rm-dist install: go install ./... +ci: clean validate test-coverage + test: build - go test -cover -v ./... + go test -cover -v -race ./... -coverage: build - ./.scripts/test.sh +test-coverage: build + ./.scripts/test-coverage.sh validate: grep -R 'const allowTestDataCapture = false' ui/ go vet ./... - @! gofmt -s -d -l . 2>&1 | grep -vE '^\.git/' + @! gofmt -s -l . 2>&1 | grep -vE '^\.git/' | grep -vE '^\.cache/' + golangci-lint run lint: build golint -set_exit_status $$(go list ./...) @@ -40,7 +43,6 @@ generate-test-data: clean: rm -rf build - rm -rf vendor go clean -.PHONY: build install test lint clean release validate generate-test-data +.PHONY: build install test lint clean release validate generate-test-data test-coverage ci @@ -1,6 +1,6 @@ # dive [![Go Report Card](https://goreportcard.com/badge/github.com/wagoodman/dive)](https://goreportcard.com/report/github.com/wagoodman/dive) -[![Pipeline Status](https://api.travis-ci.org/wagoodman/dive.svg?branch=master)](https://travis-ci.org/wagoodman/dive) +[![Pipeline Status](https://gitlab.com/wagoodman/dive/badges/master/pipeline.svg)](https://gitlab.com/wagoodman/dive/pipelines?scope=branches&page=1) **A tool for exploring a docker image, layer contents, and discovering ways to shrink your Docker image size.** @@ -147,7 +147,7 @@ or if you are running with a docker image: ```bash docker run --rm -it \ -v /var/run/docker.sock:/var/run/docker.sock \ - -e DOCKER_API_VERSION=1.37 + -e DOCKER_API_VERSION=1.37 \ wagoodman/dive:latest <dive arguments...> ``` @@ -189,6 +189,8 @@ Key Binding | Description <kbd>Ctrl + M</kbd> | Filetree view: show/hide modified files <kbd>Ctrl + U</kbd> | Filetree view: show/hide unmodified files <kbd>Ctrl + B</kbd> | Filetree view: show/hide file attributes +<kbd>PageUp</kbd> | Filetree view: scroll up a page +<kbd>PageDown</kbd> | Filetree view: scroll down a page ## UI Configuration diff --git a/cmd/analyze.go b/cmd/analyze.go index eab81f2..937378a 100644 --- a/cmd/analyze.go +++ b/cmd/analyze.go @@ -20,14 +20,14 @@ func doAnalyzeCmd(cmd *cobra.Command, args []string) { } fmt.Println("No image argument given") - cmd.Help() + _ = cmd.Help() utils.Exit(1) } userImage := args[0] if userImage == "" { fmt.Println("No image argument given") - cmd.Help() + _ = cmd.Help() utils.Exit(1) } diff --git a/cmd/root.go b/cmd/root.go index ec2dc0a..e360cbf 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -70,7 +70,7 @@ func initConfig() { viper.SetDefault("keybinding.toggle-added-files", "ctrl+a") viper.SetDefault("keybinding.toggle-removed-files", "ctrl+r") viper.SetDefault("keybinding.toggle-modified-files", "ctrl+m") - viper.SetDefault("keybinding.toggle-unchanged-files", "ctrl+u") + viper.SetDefault("keybinding.toggle-unmodified-files", "ctrl+u") viper.SetDefault("keybinding.page-up", "pgup") viper.SetDefault("keybinding.page-down", "pgdn") diff --git a/filetree/cache.go b/filetree/cache.go index 3dde39a..6e676c3 100644 --- a/filetree/cache.go +++ b/filetree/cache.go @@ -17,8 +17,6 @@ func (cache *TreeCache) Get(bottomTreeStart, bottomTreeStop, topTreeStart, topTr key := TreeCacheKey{bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop} if value, exists := cache.cache[key]; exists { return value - } else { - } value := cache.buildTree(key) cache.cache[key] = value diff --git a/filetree/data.go b/filetree/data.go index 64ceceb..743ecb0 100644 --- a/filetree/data.go +++ b/filetree/data.go @@ -10,8 +10,8 @@ import ( ) const ( - Unchanged DiffType = iota - Changed + Unmodified DiffType = iota + Modified Added Removed ) @@ -23,7 +23,7 @@ func NewNodeData() *NodeData { return &NodeData{ ViewInfo: *NewViewInfo(), FileInfo: FileInfo{}, - DiffType: Unchanged, + DiffType: Unmodified, } } @@ -64,7 +64,10 @@ func getHashFromReader(reader io.Reader) uint64 { break } - h.Write(buf[:n]) + _, err = h.Write(buf[:n]) + if err != nil { + logrus.Panic(err) + } } return h.Sum64() @@ -126,19 +129,19 @@ func (data *FileInfo) Compare(other FileInfo) DiffType { data.Mode == other.Mode && data.Uid == other.Uid && data.Gid == other.Gid { - return Unchanged + return Unmodified } } - return Changed + return Modified } // String of a DiffType func (diff DiffType) String() string { switch diff { - case Unchanged: - return "Unchanged" - case Changed: - return "Changed" + case Unmodified: + return "Unmodified" + case Modified: + return "Modified" case Added: return "Added" case Removed: @@ -154,5 +157,5 @@ func (diff DiffType) merge(other DiffType) DiffType { if diff == other { return diff } - return Changed + return Modified } diff --git a/filetree/data_test.go b/filetree/data_test.go index 7c9fad7..351d6df 100644 --- a/filetree/data_test.go +++ b/filetree/data_test.go @@ -10,23 +10,23 @@ func TestAssignDiffType(t *testing.T) { if err != nil { t.Errorf("Expected no error from fetching path. got: %v", err) } - node.Data.DiffType = Changed - if tree.Root.Children["usr"].Data.DiffType != Changed { + node.Data.DiffType = Modified + if tree.Root.Children["usr"].Data.DiffType != Modified { t.Fail() } } func TestMergeDiffTypes(t *testing.T) { - a := Unchanged - b := Unchanged + a := Unmodified + b := Unmodified merged := a.merge(b) - if merged != Unchanged { + if merged != Unmodified { t.Errorf("Expected Unchaged (0) but got %v", merged) } - a = Changed - b = Unchanged + a = Modified + b = Unmodified merged = a.merge(b) - if merged != Changed { + if merged != Modified { t.Errorf("Expected Unchaged (0) but got %v", merged) } } diff --git a/filetree/efficiency_test.go b/filetree/efficiency_test.go index e461201..831ceb5 100644 --- a/filetree/efficiency_test.go +++ b/filetree/efficiency_test.go @@ -4,19 +4,31 @@ import ( "testing" ) +func checkError(t *testing.T, err error, message string) { + if err != nil { + t.Errorf(message+": %+v", err) + } +} + func TestEfficency(t *testing.T) { trees := make([]*FileTree, 3) for idx := range trees { trees[idx] = NewFileTree() } - trees[0].AddPath("/etc/nginx/nginx.conf", FileInfo{Size: 2000}) - trees[0].AddPath("/etc/nginx/public", FileInfo{Size: 3000}) + _, _, err := trees[0].AddPath("/etc/nginx/nginx.conf", FileInfo{Size: 2000}) + checkError(t, err, "could not setup test") + + _, _, err = trees[0].AddPath("/etc/nginx/public", FileInfo{Size: 3000}) + checkError(t, err, "could not setup test") - trees[1].AddPath("/etc/nginx/nginx.conf", FileInfo{Size: 5000}) - trees[1].AddPath("/etc/athing", FileInfo{Size: 10000}) + _, _, err = trees[1].AddPath("/etc/nginx/nginx.conf", FileInfo{Size: 5000}) + checkError(t, err, "could not setup test") + _, _, err = trees[1].AddPath("/etc/athing", FileInfo{Size: 10000}) + checkError(t, err, "could not setup test") - trees[2].AddPath("/etc/.wh.nginx", *BlankFileChangeInfo("/etc/.wh.nginx")) + _, _, err = trees[2].AddPath("/etc/.wh.nginx", *BlankFileChangeInfo("/etc/.wh.nginx")) + checkError(t, err, "could not setup test") var expectedScore = 0.75 var expectedMatches = EfficiencySlice{ @@ -50,7 +62,8 @@ func TestEfficency_ScratchImage(t *testing.T) { trees[idx] = NewFileTree() } - trees[0].AddPath("/nothing", FileInfo{Size: 0}) + _, _, err := trees[0].AddPath("/nothing", FileInfo{Size: 0}) + checkError(t, err, "could not setup test") var expectedScore = 1.0 var expectedMatches = EfficiencySlice{} diff --git a/filetree/node.go b/filetree/node.go index 48fa6e4..d136f0d 100644 --- a/filetree/node.go +++ b/filetree/node.go @@ -18,10 +18,10 @@ const ( ) var diffTypeColor = map[DiffType]*color.Color{ - Added: color.New(color.FgGreen), - Removed: color.New(color.FgRed), - Changed: color.New(color.FgYellow), - Unchanged: color.New(color.Reset), + Added: color.New(color.FgGreen), + Removed: color.New(color.FgRed), + Modified: color.New(color.FgYellow), + Unmodified: color.New(color.Reset), } // NewNode creates a new FileNode relative to the given parent node with a payload. @@ -101,7 +101,10 @@ func (node *FileNode) Remove() error { return fmt.Errorf("cannot remove the tree root") } for _, child := range node.Children { - child.Remove() + err := child.Remove() + if err != nil { + return err + } } delete(node.Parent.Children, node.Name) node.Tree.Size-- @@ -290,7 +293,7 @@ func (node *FileNode) AssignDiffType(diffType DiffType) error { // compare the current node against the given node, returning a definitive DiffType. func (node *FileNode) compare(other *FileNode) DiffType { if node == nil && other == nil { - return Unchanged + return Unmodified } if node == nil && other != nil { diff --git a/filetree/node_test.go b/filetree/node_test.go index a902e48..a344475 100644 --- a/filetree/node_test.go +++ b/filetree/node_test.go @@ -56,7 +56,8 @@ func TestRemoveChild(t *testing.T) { forth := two.AddChild("forth", FileInfo{}) two.AddChild("fifth", FileInfo{}) - forth.Remove() + err := forth.Remove() + checkError(t, err, "unable to setup test") expected, actual = 4, tree.Size if expected != actual { @@ -67,7 +68,8 @@ func TestRemoveChild(t *testing.T) { t.Errorf("Expected 'forth' node to be deleted.") } - two.Remove() + err = two.Remove() + checkError(t, err, "unable to setup test") expected, actual = 2, tree.Size if expected != actual { @@ -113,7 +115,7 @@ func TestIsWhiteout(t *testing.T) { func TestDiffTypeFromAddedChildren(t *testing.T) { tree := NewFileTree() node, _, _ := tree.AddPath("/usr", *BlankFileChangeInfo("/usr")) - node.Data.DiffType = Unchanged + node.Data.DiffType = Unmodified node, _, _ = tree.AddPath("/usr/bin", *BlankFileChangeInfo("/usr/bin")) node.Data.DiffType = Added @@ -121,37 +123,42 @@ func TestDiffTypeFromAddedChildren(t *testing.T) { node, _, _ = tree.AddPath("/usr/bin2", *BlankFileChangeInfo("/usr/bin2")) node.Data.DiffType = Removed - tree.Root.Children["usr"].deriveDiffType(Unchanged) + err := tree.Root.Children["usr"].deriveDiffType(Unmodified) + checkError(t, err, "unable to setup test") - if tree.Root.Children["usr"].Data.DiffType != Changed { - t.Errorf("Expected Changed but got %v", tree.Root.Children["usr"].Data.DiffType) + if tree.Root.Children["usr"].Data.DiffType != Modified { + t.Errorf("Expected Modified but got %v", tree.Root.Children["usr"].Data.DiffType) } } func TestDiffTypeFromRemovedChildren(t *testing.T) { tree := NewFileTree() - node, _, _ := tree.AddPath("/usr", *BlankFileChangeInfo("/usr")) + _, _, _ = tree.AddPath("/usr", *BlankFileChangeInfo("/usr")) info1 := BlankFileChangeInfo("/usr/.wh.bin") - node, _, _ = tree.AddPath("/usr/.wh.bin", *info1) + node, _, _ := tree.AddPath("/usr/.wh.bin", *info1) node.Data.DiffType = Removed info2 := BlankFileChangeInfo("/usr/.wh.bin2") node, _, _ = tree.AddPath("/usr/.wh.bin2", *info2) node.Data.DiffType = Removed - tree.Root.Children["usr"].deriveDiffType(Unchanged) + err := tree.Root.Children["usr"].deriveDiffType(Unmodified) + checkError(t, err, "unable to setup test") - if tree.Root.Children["usr"].Data.DiffType != Changed { - t.Errorf("Expected Changed but got %v", tree.Root.Children["usr"].Data.DiffType) + if tree.Root.Children["usr"].Data.DiffType != Modified { + t.Errorf("Expected Modified but got %v", tree.Root.Children["usr"].Data.DiffType) } } func TestDirSize(t *testing.T) { tree1 := NewFileTree() - tree1.AddPath("/etc/nginx/public1", FileInfo{Size: 100}) - tree1.AddPath("/etc/nginx/thing1", FileInfo{Size: 200}) - tree1.AddPath("/etc/nginx/public3/thing2", FileInfo{Size: 300}) + _, _, err := tree1.AddPath("/etc/nginx/public1", FileInfo{Size: 100}) + checkError(t, err, "unable to setup test") + _, _, err = tree1.AddPath("/etc/nginx/thing1", FileInfo{Size: 200}) + checkError(t, err, "unable to setup test") + _, _, err = tree1.AddPath("/etc/nginx/public3/thing2", FileInfo{Size: 300}) + checkError(t, err, "unable to setup test") node, _ := tree1.GetNode("/etc/nginx") expected, actual := "---------- 0:0 600 B ", node.MetadataString() diff --git a/filetree/tree.go b/filetree/tree.go index b225224..192ad8d 100644 --- a/filetree/tree.go +++ b/filetree/tree.go @@ -242,6 +242,11 @@ func (tree *FileTree) AddPath(path string, data FileInfo) (*FileNode, []*FileNod if node.Children[name] != nil { node = node.Children[name] } else { + // don't add paths that should be deleted + if strings.HasPrefix(name, doubleWhiteoutPrefix) { + return nil, addedNodes, nil + } + // don't attach the payload. The payload is destined for the // Path's end node, not any intermediary node. node = node.AddChild(name, FileInfo{}) @@ -249,7 +254,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'", name)) + return node, addedNodes, fmt.Errorf(fmt.Sprintf("could not add child node: '%s' (path:'%s')", name, path)) } } @@ -326,9 +331,15 @@ func (tree *FileTree) CompareAndMark(upper *FileTree) error { // take note of the comparison results on each note in the owning tree. for _, pair := range modifications { if pair.final > 0 { - pair.lowerNode.AssignDiffType(pair.final) - } else if pair.lowerNode.Data.DiffType == Unchanged { - pair.lowerNode.deriveDiffType(pair.tentative) + err = pair.lowerNode.AssignDiffType(pair.final) + if err != nil { + return err + } + } else if pair.lowerNode.Data.DiffType == Unmodified { + err = pair.lowerNode.deriveDiffType(pair.tentative) + if err != nil { + return err + } } // persist the upper's payload on the owning tree diff --git a/filetree/tree_test.go b/filetree/tree_test.go index b1a2c6b..fc57036 100644 --- a/filetree/tree_test.go +++ b/filetree/tree_test.go @@ -87,12 +87,30 @@ func TestString(t *testing.T) { func TestStringBetween(t *testing.T) { tree := NewFileTree() - tree.AddPath("/etc/nginx/nginx.conf", FileInfo{}) - tree.AddPath("/etc/nginx/public", FileInfo{}) - tree.AddPath("/var/run/systemd", FileInfo{}) - tree.AddPath("/var/run/bashful", FileInfo{}) - tree.AddPath("/tmp", FileInfo{}) - tree.AddPath("/tmp/nonsense", FileInfo{}) + _, _, err := tree.AddPath("/etc/nginx/nginx.conf", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/etc/nginx/public", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/var/run/systemd", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/var/run/bashful", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/tmp", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/tmp/nonsense", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } expected := `│ └── public @@ -109,12 +127,30 @@ func TestStringBetween(t *testing.T) { func TestAddPath(t *testing.T) { tree := NewFileTree() - tree.AddPath("/etc/nginx/nginx.conf", FileInfo{}) - tree.AddPath("/etc/nginx/public", FileInfo{}) - tree.AddPath("/var/run/systemd", FileInfo{}) - tree.AddPath("/var/run/bashful", FileInfo{}) - tree.AddPath("/tmp", FileInfo{}) - tree.AddPath("/tmp/nonsense", FileInfo{}) + _, _, err := tree.AddPath("/etc/nginx/nginx.conf", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/etc/nginx/public", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/var/run/systemd", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/var/run/bashful", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/tmp", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/tmp/nonsense", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } expected := `├── etc @@ -136,17 +172,65 @@ func TestAddPath(t *testing.T) { } +func TestAddWhiteoutPath(t *testing.T) { + tree := NewFileTree() + node, _, err := tree.AddPath("usr/local/lib/python3.7/site-packages/pip/.wh..wh..opq", FileInfo{}) + if err != nil { + t.Errorf("expected no error but got: %v", err) + } + if node != nil { + t.Errorf("expected node to be nil, but got: %v", node) + } + expected := + `└── usr + └── local + └── lib + └── python3.7 + └── site-packages + └── pip +` + actual := tree.String(false) + + if expected != actual { + t.Errorf("Expected tree string:\n--->%s<---\nGot:\n--->%s<---", expected, actual) + } +} + func TestRemovePath(t *testing.T) { tree := NewFileTree() - tree.AddPath("/etc/nginx/nginx.conf", FileInfo{}) - tree.AddPath("/etc/nginx/public", FileInfo{}) - tree.AddPath("/var/run/systemd", FileInfo{}) - tree.AddPath("/var/run/bashful", FileInfo{}) - tree.AddPath("/tmp", FileInfo{}) - tree.AddPath("/tmp/nonsense", FileInfo{}) + _, _, err := tree.AddPath("/etc/nginx/nginx.conf", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/etc/nginx/public", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/var/run/systemd", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/var/run/bashful", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/tmp", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree.AddPath("/tmp/nonsense", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } - tree.RemovePath("/var/run/bashful") - tree.RemovePath("/tmp") + err = tree.RemovePath("/var/run/bashful") + if err != nil { + t.Errorf("could not setup test: %v", err) + } + err = tree.RemovePath("/tmp") + if err != nil { + t.Errorf("could not setup test: %v", err) + } expected := `├── etc @@ -173,24 +257,57 @@ func TestStack(t *testing.T) { tree1 := NewFileTree() - tree1.AddPath("/etc/nginx/public", FileInfo{}) - tree1.AddPath(payloadKey, FileInfo{}) - tree1.AddPath("/var/run/bashful", FileInfo{}) - tree1.AddPath("/tmp", FileInfo{}) - tree1.AddPath("/tmp/nonsense", FileInfo{}) + _, _, err := tree1.AddPath("/etc/nginx/public", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree1.AddPath(payloadKey, FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree1.AddPath("/var/run/bashful", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree1.AddPath("/tmp", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree1.AddPath("/tmp/nonsense", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } tree2 := NewFileTree() // add new files - tree2.AddPath("/etc/nginx/nginx.conf", FileInfo{}) + _, _, err = tree2.AddPath("/etc/nginx/nginx.conf", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } // modify current files - tree2.AddPath(payloadKey, payloadValue) + _, _, err = tree2.AddPath(payloadKey, payloadValue) + if err != nil { + t.Errorf("could not setup test: %v", err) + } // whiteout the following files - tree2.AddPath("/var/run/.wh.bashful", FileInfo{}) - tree2.AddPath("/.wh.tmp", FileInfo{}) + _, _, err = tree2.AddPath("/var/run/.wh.bashful", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } + _, _, err = tree2.AddPath("/.wh.tmp", FileInfo{}) + if err != nil { + t.Errorf("could not setup test: %v", err) + } // ignore opaque whiteout files entirely - tree2.AddPath("/.wh..wh..opq", FileInfo{}) + node, _, err := tree2.AddPath("/.wh..wh..opq", FileInfo{}) + if err != nil { + t.Errorf("expected no error on whiteout file add, but got %v", err) + } + if node != nil { + t.Errorf("expected no node on whiteout file add, but got %v", node) + } - err := tree1.Stack(tree2) + err = tree1.Stack(tree2) if err != nil { t.Errorf("Could not stack refTrees: %v", err) @@ -206,12 +323,12 @@ func TestStack(t *testing.T) { └── systemd ` - node, err := tree1.GetNode(payloadKey) + node, err = tree1.GetNode(payloadKey) if err != nil { |