From 3a9796619c235e99cc7aad288f6e83f0cd448b3a Mon Sep 17 00:00:00 2001
From: Alex Goodman <wagoodman@gmail.com>
Date: Mon, 1 Oct 2018 21:50:05 -0400
Subject: [PATCH] renamed to dive; use cobra; rm dep; imagehistory fix

---
 .vscode/launch.json |  24 ----------
 Gopkg.lock          | 104 --------------------------------------------
 Gopkg.toml          |  43 ------------------
 Makefile            |  25 ++++-------
 README.md           |  10 ++---
 cmd/analyze.go      |  39 +++++++++++++++++
 cmd/build.go        |  51 ++++++++++++++++++++++
 cmd/die/main.go     |  36 ---------------
 cmd/root.go         |  89 +++++++++++++++++++++++++++++++++++++
 image/image.go      |   6 +--
 main.go             |  27 ++++++++++++
 ui/filetreeview.go  |   2 +-
 ui/layerview.go     |   2 +-
 ui/ui.go            |   4 +-
 14 files changed, 226 insertions(+), 236 deletions(-)
 delete mode 100644 .vscode/launch.json
 delete mode 100644 Gopkg.lock
 delete mode 100644 Gopkg.toml
 create mode 100644 cmd/analyze.go
 create mode 100644 cmd/build.go
 delete mode 100644 cmd/die/main.go
 create mode 100644 cmd/root.go
 create mode 100644 main.go

diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index 3296f89..0000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    // Use IntelliSense to learn about possible attributes.
-    // Hover to view descriptions of existing attributes.
-    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
-    "version": "0.2.0",
-    "configurations": [
-        {
-            "name": "Launch",
-            "type": "go",
-            "request": "launch",
-            "mode": "debug",
-            "remotePath": "",
-            "port": 2345,
-            "host": "127.0.0.1",
-            "program": "${workspaceRoot}/cmd/die/main.go",
-            "externalConsole": true,
-            "env": {
-                "TERM": "xterm-256color"
-            },
-            "args": ["die-test"],
-            "showLog": true
-        }
-    ]
-}
\ No newline at end of file
diff --git a/Gopkg.lock b/Gopkg.lock
deleted file mode 100644
index 5166b9e..0000000
--- a/Gopkg.lock
+++ /dev/null
@@ -1,104 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
-  name = "github.com/Microsoft/go-winio"
-  packages = ["."]
-  revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
-  version = "v0.4.7"
-
-[[projects]]
-  name = "github.com/docker/distribution"
-  packages = [
-    "digest",
-    "reference"
-  ]
-  revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
-  version = "v2.6.2"
-
-[[projects]]
-  name = "github.com/docker/docker"
-  packages = [
-    "api/types",
-    "api/types/blkiodev",
-    "api/types/container",
-    "api/types/events",
-    "api/types/filters",
-    "api/types/mount",
-    "api/types/network",
-    "api/types/reference",
-    "api/types/registry",
-    "api/types/strslice",
-    "api/types/swarm",
-    "api/types/time",
-    "api/types/versions",
-    "api/types/volume",
-    "client",
-    "pkg/tlsconfig"
-  ]
-  revision = "092cba3727bb9b4a2f0e922cd6c0f93ea270e363"
-  version = "v1.13.1"
-
-[[projects]]
-  name = "github.com/docker/go-connections"
-  packages = [
-    "nat",
-    "sockets",
-    "tlsconfig"
-  ]
-  revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
-  version = "v0.3.0"
-
-[[projects]]
-  name = "github.com/docker/go-units"
-  packages = ["."]
-  revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
-  version = "v0.3.3"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/jroimartin/gocui"
-  packages = ["."]
-  revision = "c055c87ae801372cd74a0839b972db4f7697ae5f"
-
-[[projects]]
-  name = "github.com/mattn/go-runewidth"
-  packages = ["."]
-  revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
-  version = "v0.0.2"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/nsf/termbox-go"
-  packages = ["."]
-  revision = "21a4d435a86280a2927985fd6296de56cbce453e"
-
-[[projects]]
-  name = "github.com/pkg/errors"
-  packages = ["."]
-  revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
-  version = "v0.8.0"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/net"
-  packages = [
-    "context",
-    "context/ctxhttp",
-    "internal/socks",
-    "proxy"
-  ]
-  revision = "1e491301e022f8f977054da4c2d852decd59571f"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/sys"
-  packages = ["windows"]
-  revision = "c11f84a56e43e20a78cee75a7c034031ecf57d1f"
-
-[solve-meta]
-  analyzer-name = "dep"
-  analyzer-version = 1
-  inputs-digest = "73c0fae1988538f4def02f2bd28830793264b4260b25d078b561413085a81845"
-  solver-name = "gps-cdcl"
-  solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
deleted file mode 100644
index 2fa2eba..0000000
--- a/Gopkg.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-# Gopkg.toml example
-#
-# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
-# for detailed Gopkg.toml documentation.
-#
-# required = ["github.com/user/thing/cmd/thing"]
-# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
-#
-# [[constraint]]
-#   name = "github.com/user/project"
-#   version = "1.0.0"
-#
-# [[constraint]]
-#   name = "github.com/user/project2"
-#   branch = "dev"
-#   source = "github.com/myfork/project2"
-#
-# [[override]]
-#   name = "github.com/x/y"
-#   version = "2.4.0"
-#
-# [prune]
-#   non-go = false
-#   go-tests = true
-#   unused-packages = true
-
-
-[[constraint]]
-  name = "github.com/docker/docker"
-  version = "1.13.1"
-
-[[constraint]]
-  name = "github.com/jroimartin/gocui"
-  # version = "0.3.0"
-  branch = "master"
-
-[[constraint]]
-  branch = "master"
-  name = "golang.org/x/net"
-
-[prune]
-  go-tests = true
-  unused-packages = true
diff --git a/Makefile b/Makefile
index 5af1d41..0aea4cd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,35 +1,26 @@
-BIN = die
+BIN = dive
 
 all: clean build
 
 run: build
-	docker image ls | grep "die-test" >/dev/null || docker build -t die-test:latest .
+	docker image ls | grep "dive-test" >/dev/null || docker build -t dive-test:latest .
 	./build/$(BIN) die-test
 
-build: #deps
-	go build -o build/$(BIN) ./cmd/...
+build:
+	go build -o build/$(BIN)
 
-install: deps
+install:
 	go install ./...
 
-deps:
-	command -v $(GOPATH)/bin/dep >/dev/null || go get -u github.com/golang/dep/cmd/dep
-	$(GOPATH)/bin/dep ensure
-
 test: build
-	@! git grep tcell -- ':!tui/' ':!Gopkg.lock' ':!Gopkg.toml' ':!Makefile'
 	go test -v ./...
 
-lint: lintdeps build
-	golint -set_exit_status $$(go list ./... | grep -v /vendor/)
-
-lintdeps:
-	go get -d -v -t ./...
-	command -v golint >/dev/null || go get -u github.com/golang/lint/golint
+lint: build
+	golint -set_exit_status $$(go list ./...)
 
 clean:
 	rm -rf build
 	rm -rf vendor
 	go clean
 
-.PHONY: build install deps test lint lintdeps clean
+.PHONY: build install test lint clean
diff --git a/README.md b/README.md
index e4b803e..cc94dc0 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
-# docker-image-explorer
+# dive
+
+A tool for interrogating docker images.
+
 ```
 docker build -t die-test:latest .
 go run main.go
@@ -6,9 +9,6 @@ go run main.go
 
 # TODO:
 
-- [x] Extract docker layers from api
-- [x] Represent layers as generic tree
-- [x] Stack ordere tree list together as fake unionfs tree
 - [ ] Diff trees
-- [ ] Add ui for browsing layers
+
 - [ ] Add ui for diffing stack to layer
diff --git a/cmd/analyze.go b/cmd/analyze.go
new file mode 100644
index 0000000..88745e3
--- /dev/null
+++ b/cmd/analyze.go
@@ -0,0 +1,39 @@
+// Copyright © 2018 Alex Goodman
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package cmd
+
+import (
+	"github.com/spf13/cobra"
+	"fmt"
+	"os"
+	"github.com/wagoodman/dive/image"
+	"github.com/wagoodman/dive/ui"
+)
+
+func analyze(cmd *cobra.Command, args []string) {
+	userImage := args[0]
+	if userImage == "" {
+		fmt.Println("No image argument given")
+		os.Exit(1)
+	}
+	manifest, refTrees := image.InitializeData(userImage)
+	ui.Run(manifest, refTrees)
+}
\ No newline at end of file
diff --git a/cmd/build.go b/cmd/build.go
new file mode 100644
index 0000000..99ebdd8
--- /dev/null
+++ b/cmd/build.go
@@ -0,0 +1,51 @@
+// Copyright © 2018 Alex Goodman
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package cmd
+
+import (
+	"fmt"
+
+	"github.com/spf13/cobra"
+)
+
+// buildCmd represents the build command
+var buildCmd = &cobra.Command{
+	Use:   "build",
+	Short: "Build and analyze a docker image",
+	Long: `Build and analyze a docker image`,
+	Run: func(cmd *cobra.Command, args []string) {
+		fmt.Println("build called")
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(buildCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// buildCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// buildCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/die/main.go b/cmd/die/main.go
deleted file mode 100644
index fa9b019..0000000
--- a/cmd/die/main.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"log"
-	"os"
-
-	"github.com/urfave/cli"
-	"github.com/wagoodman/docker-image-explorer/image"
-	"github.com/wagoodman/docker-image-explorer/ui"
-)
-
-const name = "die"
-const version = "v0.0.0"
-const author = "wagoodman"
-
-func main() {
-	app := cli.NewApp()
-	app.Name = "die"
-	app.Usage = "Explore your docker images"
-	app.Action = func(c *cli.Context) error {
-		userImage := c.Args().Get(0)
-		if userImage == "" {
-			fmt.Println("No image argument given")
-			os.Exit(1)
-		}
-		manifest, refTrees := image.InitializeData(userImage)
-		ui.Run(manifest, refTrees)
-		return nil
-	}
-
-	err := app.Run(os.Args)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/cmd/root.go b/cmd/root.go
new file mode 100644
index 0000000..91d46a7
--- /dev/null
+++ b/cmd/root.go
@@ -0,0 +1,89 @@
+// Copyright © 2018 Alex Goodman
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package cmd
+
+import (
+	"fmt"
+	"os"
+
+	homedir "github.com/mitchellh/go-homedir"
+	"github.com/spf13/cobra"
+	"github.com/spf13/viper"
+)
+
+var cfgFile string
+
+// rootCmd represents the base command when called without any subcommands
+var rootCmd = &cobra.Command{
+	Use:   "dive",
+	Short: "Docker Image Visualizer & Explorer",
+	Long: `Docker Image Visualizer & Explorer`,
+	Args: cobra.ExactArgs(1),
+	Run: analyze,
+}
+
+// Execute adds all child commands to the root command and sets flags appropriately.
+// This is called by main.main(). It only needs to happen once to the rootCmd.
+func Execute() {
+	if err := rootCmd.Execute(); err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+}
+
+func init() {
+	cobra.OnInitialize(initConfig)
+
+	// Here you will define your flags and configuration settings.
+	// Cobra supports persistent flags, which, if defined here,
+	// will be global for your application.
+	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.dive.yaml)")
+
+	// Cobra also supports local flags, which will only run
+	// when this action is called directly.
+	rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
+
+// initConfig reads in config file and ENV variables if set.
+func initConfig() {
+	if cfgFile != "" {
+		// Use config file from the flag.
+		viper.SetConfigFile(cfgFile)
+	} else {
+		// Find home directory.
+		home, err := homedir.Dir()
+		if err != nil {
+			fmt.Println(err)
+			os.Exit(1)
+		}
+
+		// Search config in home directory with name ".dive" (without extension).
+		viper.AddConfigPath(home)
+		viper.SetConfigName(".dive")
+	}
+
+	viper.AutomaticEnv() // read in environment variables that match
+
+	// If a config file is found, read it in.
+	if err := viper.ReadInConfig(); err == nil {
+		fmt.Println("Using config file:", viper.ConfigFileUsed())
+	}
+}
diff --git a/image/image.go b/image/image.go
index 6560d49..b45c980 100644
--- a/image/image.go
+++ b/image/image.go
@@ -12,10 +12,10 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/image"
 	"github.com/docker/docker/client"
 	humanize "github.com/dustin/go-humanize"
-	"github.com/wagoodman/docker-image-explorer/filetree"
+	"github.com/wagoodman/dive/filetree"
 	"golang.org/x/net/context"
 	"strconv"
 )
@@ -53,7 +53,7 @@ func NewManifest(reader *tar.Reader, header *tar.Header) ImageManifest {
 
 type Layer struct {
 	TarPath  string
-	History  types.ImageHistory
+	History  image.HistoryResponseItem
 	Index    int
 	Tree     *filetree.FileTree
 	RefTrees []*filetree.FileTree
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..d6e186f
--- /dev/null
+++ b/main.go
@@ -0,0 +1,27 @@
+// Copyright © 2018 Alex Goodman
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package main
+
+import "github.com/wagoodman/dive/cmd"
+
+func main() {
+	cmd.Execute()
+}
diff --git a/ui/filetreeview.go b/ui/filetreeview.go
index 49c80ee..05eb56a 100644
--- a/ui/filetreeview.go
+++ b/ui/filetreeview.go
@@ -6,7 +6,7 @@ import (
 	"strings"
 
 	"github.com/jroimartin/gocui"
-	"github.com/wagoodman/docker-image-explorer/filetree"
+	"github.com/wagoodman/dive/filetree"
 	"github.com/lunixbochs/vtclean"
 )
 
diff --git a/ui/layerview.go b/ui/layerview.go
index b4558a3..d83822c 100644
--- a/ui/layerview.go
+++ b/ui/layerview.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 
 	"github.com/jroimartin/gocui"
-	"github.com/wagoodman/docker-image-explorer/image"
+	"github.com/wagoodman/dive/image"
 	"github.com/lunixbochs/vtclean"
 )
 
diff --git a/ui/ui.go b/ui/ui.go
index e8b4168..f9458ec 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -6,8 +6,8 @@ import (
 	"log"
 
 	"github.com/jroimartin/gocui"
-	"github.com/wagoodman/docker-image-explorer/filetree"
-	"github.com/wagoodman/docker-image-explorer/image"
+	"github.com/wagoodman/dive/filetree"
+	"github.com/wagoodman/dive/image"
 	"github.com/fatih/color"
 )