summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Goodman <wagoodman@users.noreply.github.com>2019-07-21 15:44:52 -0400
committerGitHub <noreply@github.com>2019-07-21 15:44:52 -0400
commit9384069d766826b2dc7fc56bcbc57d12cd2ff51e (patch)
tree767c0963758705c8dd169741aa72963cc023cf0f
parent57b1a3d5228872eba6589b0ae38ceccabd0f3344 (diff)
parentea0de60dc05cdb5b3fbf75655121b92c6ab93ec2 (diff)
Merge branch 'master' into format-fixes
-rw-r--r--.dockerignore2
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml26
-rwxr-xr-x.scripts/test-coverage.sh (renamed from .scripts/test.sh)0
-rw-r--r--.travis.yml34
-rw-r--r--Makefile16
-rw-r--r--README.md6
-rw-r--r--cmd/analyze.go4
-rw-r--r--cmd/root.go2
-rw-r--r--filetree/cache.go2
-rw-r--r--filetree/data.go25
-rw-r--r--filetree/data_test.go16
-rw-r--r--filetree/efficiency_test.go25
-rw-r--r--filetree/node.go15
-rw-r--r--filetree/node_test.go35
-rw-r--r--filetree/tree.go19
-rw-r--r--filetree/tree_test.go379
-rw-r--r--go.mod12
-rw-r--r--go.sum157
-rw-r--r--image/docker_image.go10
-rw-r--r--runtime/ci/evaluator.go5
-rw-r--r--ui/details_controller.go23
-rw-r--r--ui/filetree_controller.go55
-rw-r--r--ui/filetree_viewmodel.go22
-rw-r--r--ui/filetree_viewmodel_test.go25
-rw-r--r--ui/filter_controller.go12
-rw-r--r--ui/layer_controller.go32
-rw-r--r--ui/status_controller.go11
-rw-r--r--ui/ui.go52
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
diff --git a/.gitignore b/.gitignore
index 16fccd1..149cdc3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/Makefile b/Makefile
index ee0266c..e31f316 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/README.md b/README.md
index 5121130..d13b1b2 100644
--- a/README.md
+++ b/README.md
@@ -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 {