From ed784c7a95657b73bcdaab016b2ff56a7a27f347 Mon Sep 17 00:00:00 2001 From: Nate Jones Date: Fri, 10 Jun 2016 21:13:42 -0700 Subject: [PATCH] added non-human numeric output, closes #25 --- README.md | 35 +++++++++++++++++++++++++++++++++++ images.go | 45 ++++++++++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index eeb5f4e..3c89148 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,41 @@ $ dockviz images -t -i └─316b678ddf48 Virtual Size: 70.8 MB Tags: ubuntu:13.04, ubuntu:raring ``` +Showing non-human numbers, for precision: + +``` +$ dockviz images -t -i -c +└─511136ea3c5a Size: 0 + ├─f10ebce2c0e1 Size: 103675325 + │ └─82cdea7ab5b5 Size: 255455 + │ └─5dbd9cb5a02f Size: 1919 + │ └─74fe38d11401 Size: 105667193 Tags: ubuntu:12.04, ubuntu:precise + ├─ef519c9ee91a Size: 100930679 + │ └─07302703becc Size: 250998 + │ └─cf8dc907452c Size: 1919 + │ └─a7cf8ae4e998 Size: 70094270 Tags: ubuntu:12.10, ubuntu:quantal + │ ├─e18d8001204e Size: 29352 + │ │ └─d0525208a46c Size: 71 + │ │ └─59dac4bae93b Size: 71150930 + │ │ └─89541b3b35f2 Size: 269335966 + │ │ └─7dac4e98548e Size: 0 + │ │ └─341d0cc3fac8 Size: 0 + │ │ └─2f96171d2098 Size: 0 + │ │ └─67b8b7262a67 Size: 1866379 + │ │ └─0fe9a2bc50fe Size: 656 + │ │ └─8c32832f07ba Size: 383 + │ │ └─cc4e1358bc80 Size: 0 + │ │ └─5c0d04fba9df Size: 0 Tags: nate/mongodb:latest + │ └─398d592f2009 Size: 70917743 + │ └─0cd8e7f50270 Size: 1418392 + │ └─594b6f8e6f92 Size: 0 + │ └─f832a63e87a4 Size: 0 Tags: redis:latest + └─02dae1c13f51 Size: 98348330 + └─e7206bfc66aa Size: 190007 + └─cb12405ee8fa Size: 1903 + └─316b678ddf48 Size: 70822908 Tags: ubuntu:13.04, ubuntu:raring +``` + # Running Dockviz supports connecting to the Docker daemon directly. It defaults to `unix:///var/run/docker.sock`, but respects the following as well: diff --git a/images.go b/images.go index 1f6aec6..d2145df 100644 --- a/images.go +++ b/images.go @@ -32,6 +32,13 @@ type ImagesCommand struct { NoTruncate bool `short:"n" long:"no-trunc" description:"Don't truncate the image IDs."` Incremental bool `short:"i" long:"incremental" description:"Display image size as incremental rather than cumulative."` OnlyLabelled bool `short:"l" long:"only-labelled" description:"Print only labelled images/containers."` + NoHuman bool `short:"c" long:"no-human" description:"Don't humanize the sizes."` +} + +type DisplayOpts struct { + NoTruncate bool + Incremental bool + NoHuman bool } var imagesCommand ImagesCommand @@ -134,7 +141,12 @@ func (x *ImagesCommand) Execute(args []string) error { } if imagesCommand.Tree { - fmt.Print(jsonToTree(roots, imagesByParent, imagesCommand.NoTruncate, imagesCommand.Incremental)) + dispOpts := DisplayOpts{ + imagesCommand.NoTruncate, + imagesCommand.Incremental, + imagesCommand.NoHuman, + } + fmt.Print(jsonToTree(roots, imagesByParent, dispOpts)) } if imagesCommand.Dot { fmt.Print(jsonToDot(roots, imagesByParent)) @@ -246,10 +258,10 @@ IMAGES: return startImage, nil } -func jsonToTree(images []Image, byParent map[string][]Image, noTrunc bool, incremental bool) string { +func jsonToTree(images []Image, byParent map[string][]Image, dispOpts DisplayOpts) string { var buffer bytes.Buffer - jsonToText(&buffer, images, byParent, noTrunc, incremental, "") + jsonToText(&buffer, images, byParent, dispOpts, "") return buffer.String() } @@ -318,35 +330,35 @@ func filterImages(images *[]Image, byParent *map[string][]Image) (filteredImages return filteredImages, filteredChildren } -func jsonToText(buffer *bytes.Buffer, images []Image, byParent map[string][]Image, noTrunc bool, incremental bool, prefix string) { +func jsonToText(buffer *bytes.Buffer, images []Image, byParent map[string][]Image, dispOpts DisplayOpts, prefix string) { var length = len(images) if length > 1 { for index, image := range images { var nextPrefix string = "" if index+1 == length { - PrintTreeNode(buffer, image, noTrunc, incremental, prefix+"└─") + PrintTreeNode(buffer, image, dispOpts, prefix+"└─") nextPrefix = " " } else { - PrintTreeNode(buffer, image, noTrunc, incremental, prefix+"├─") + PrintTreeNode(buffer, image, dispOpts, prefix+"├─") nextPrefix = "│ " } if subimages, exists := byParent[image.Id]; exists { - jsonToText(buffer, subimages, byParent, noTrunc, incremental, prefix+nextPrefix) + jsonToText(buffer, subimages, byParent, dispOpts, prefix+nextPrefix) } } } else { for _, image := range images { - PrintTreeNode(buffer, image, noTrunc, incremental, prefix+"└─") + PrintTreeNode(buffer, image, dispOpts, prefix+"└─") if subimages, exists := byParent[image.Id]; exists { - jsonToText(buffer, subimages, byParent, noTrunc, incremental, prefix+" ") + jsonToText(buffer, subimages, byParent, dispOpts, prefix+" ") } } } } -func PrintTreeNode(buffer *bytes.Buffer, image Image, noTrunc bool, incremental bool, prefix string) { +func PrintTreeNode(buffer *bytes.Buffer, image Image, dispOpts DisplayOpts, prefix string) { var imageID string - if noTrunc { + if dispOpts.NoTruncate { imageID = image.OrigId } else { imageID = truncate(image.OrigId, 12) @@ -354,7 +366,7 @@ func PrintTreeNode(buffer *bytes.Buffer, image Image, noTrunc bool, incremental var size int64 var sizeLabel string - if incremental { + if dispOpts.Incremental { sizeLabel = "Size" size = image.Size } else { @@ -362,7 +374,14 @@ func PrintTreeNode(buffer *bytes.Buffer, image Image, noTrunc bool, incremental size = image.VirtualSize } - buffer.WriteString(fmt.Sprintf("%s%s %s: %s", prefix, imageID, sizeLabel, humanSize(size))) + var sizeStr string + if dispOpts.NoHuman { + sizeStr = strconv.FormatInt(size, 10) + } else { + sizeStr = humanSize(size) + } + + buffer.WriteString(fmt.Sprintf("%s%s %s: %s", prefix, imageID, sizeLabel, sizeStr)) if image.RepoTags[0] != ":" { buffer.WriteString(fmt.Sprintf(" Tags: %s\n", strings.Join(image.RepoTags, ", "))) } else {