Browse code

Fix duplicate display of dangling images

Signed-off-by: Andy Goldstein <agoldste@redhat.com>

Andy Goldstein authored on 2015/03/18 23:11:01
Showing 2 changed files
... ...
@@ -1518,29 +1518,32 @@ func (cli *DockerCli) CmdImages(args ...string) error {
1518 1518
 				outID = common.TruncateID(outID)
1519 1519
 			}
1520 1520
 
1521
-			// Tags referring to this image ID.
1522
-			for _, repotag := range out.GetList("RepoTags") {
1523
-				repo, tag := parsers.ParseRepositoryTag(repotag)
1521
+			repoTags := out.GetList("RepoTags")
1522
+			repoDigests := out.GetList("RepoDigests")
1524 1523
 
1525
-				if !*quiet {
1526
-					if *showDigests {
1527
-						fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, "<none>", outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
1528
-					} else {
1529
-						fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
1530
-					}
1524
+			if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" {
1525
+				// dangling image - clear out either repoTags or repoDigsts so we only show it once below
1526
+				repoDigests = []string{}
1527
+			}
1528
+
1529
+			// combine the tags and digests lists
1530
+			tagsAndDigests := append(repoTags, repoDigests...)
1531
+			for _, repoAndRef := range tagsAndDigests {
1532
+				repo, ref := parsers.ParseRepositoryTag(repoAndRef)
1533
+				// default tag and digest to none - if there's a value, it'll be set below
1534
+				tag := "<none>"
1535
+				digest := "<none>"
1536
+				if utils.DigestReference(ref) {
1537
+					digest = ref
1531 1538
 				} else {
1532
-					fmt.Fprintln(w, outID)
1539
+					tag = ref
1533 1540
 				}
1534
-			}
1535 1541
 
1536
-			// Digests referring to this image ID.
1537
-			for _, repoDigest := range out.GetList("RepoDigests") {
1538
-				repo, digest := parsers.ParseRepositoryTag(repoDigest)
1539 1542
 				if !*quiet {
1540 1543
 					if *showDigests {
1541
-						fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, "<none>", digest, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
1544
+						fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
1542 1545
 					} else {
1543
-						fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, "<none>", outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
1546
+						fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
1544 1547
 					}
1545 1548
 				} else {
1546 1549
 					fmt.Fprintln(w, outID)
... ...
@@ -8,6 +8,8 @@ import (
8 8
 	"strings"
9 9
 	"testing"
10 10
 	"time"
11
+
12
+	"github.com/docker/docker/pkg/common"
11 13
 )
12 14
 
13 15
 func TestImagesEnsureImageIsListed(t *testing.T) {
... ...
@@ -176,3 +178,44 @@ func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
176 176
 
177 177
 	logDone("images - white space trimming and lower casing")
178 178
 }
179
+
180
+func TestImagesEnsureDanglingImageOnlyListedOnce(t *testing.T) {
181
+	defer deleteAllContainers()
182
+
183
+	// create container 1
184
+	c := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
185
+	out, _, err := runCommandWithOutput(c)
186
+	if err != nil {
187
+		t.Fatalf("error running busybox: %s, %v", out, err)
188
+	}
189
+	containerId1 := strings.TrimSpace(out)
190
+
191
+	// tag as foobox
192
+	c = exec.Command(dockerBinary, "commit", containerId1, "foobox")
193
+	out, _, err = runCommandWithOutput(c)
194
+	if err != nil {
195
+		t.Fatalf("error tagging foobox: %s", err)
196
+	}
197
+	imageId := common.TruncateID(strings.TrimSpace(out))
198
+	defer deleteImages(imageId)
199
+
200
+	// overwrite the tag, making the previous image dangling
201
+	c = exec.Command(dockerBinary, "tag", "-f", "busybox", "foobox")
202
+	out, _, err = runCommandWithOutput(c)
203
+	if err != nil {
204
+		t.Fatalf("error tagging foobox: %s", err)
205
+	}
206
+	defer deleteImages("foobox")
207
+
208
+	c = exec.Command(dockerBinary, "images", "-q", "-f", "dangling=true")
209
+	out, _, err = runCommandWithOutput(c)
210
+	if err != nil {
211
+		t.Fatalf("listing images failed with errors: %s, %v", out, err)
212
+	}
213
+
214
+	if e, a := 1, strings.Count(out, imageId); e != a {
215
+		t.Fatalf("expected 1 dangling image, got %d: %s", a, out)
216
+	}
217
+
218
+	logDone("images - dangling image only listed once")
219
+}