Browse code

rework images JSON

Nate Jones authored on 2013/10/06 14:44:04
Showing 4 changed files
... ...
@@ -9,12 +9,12 @@ type APIHistory struct {
9 9
 }
10 10
 
11 11
 type APIImages struct {
12
-	Repository  string `json:",omitempty"`
13
-	Tag         string `json:",omitempty"`
14
-	ID          string `json:"Id"`
12
+	ID          string   `json:"Id"`
13
+	RepoTags    []string `json:",omitempty"`
15 14
 	Created     int64
16 15
 	Size        int64
17 16
 	VirtualSize int64
17
+	ParentId    string `json:",omitempty"`
18 18
 }
19 19
 
20 20
 type APIInfo struct {
... ...
@@ -1097,27 +1097,29 @@ func (cli *DockerCli) CmdImages(args ...string) error {
1097 1097
 			fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED\tSIZE")
1098 1098
 		}
1099 1099
 
1100
+		var repo string
1101
+		var tag string
1100 1102
 		for _, out := range outs {
1101
-			if out.Repository == "" {
1102
-				out.Repository = "<none>"
1103
-			}
1104
-			if out.Tag == "" {
1105
-				out.Tag = "<none>"
1106
-			}
1103
+			for _, repotag := range out.RepoTags {
1107 1104
 
1108
-			if !*noTrunc {
1109
-				out.ID = utils.TruncateID(out.ID)
1110
-			}
1105
+				components := strings.SplitN(repotag, ":", 2)
1106
+				repo = components[0]
1107
+				tag = components[1]
1111 1108
 
1112
-			if !*quiet {
1113
-				fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t", out.Repository, out.Tag, out.ID, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))))
1114
-				if out.VirtualSize > 0 {
1115
-					fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.Size), utils.HumanSize(out.VirtualSize))
1109
+				if !*noTrunc {
1110
+					out.ID = utils.TruncateID(out.ID)
1111
+				}
1112
+
1113
+				if !*quiet {
1114
+					fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t", repo, tag, out.ID, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))))
1115
+					if out.VirtualSize > 0 {
1116
+						fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.Size), utils.HumanSize(out.VirtualSize))
1117
+					} else {
1118
+						fmt.Fprintf(w, "%s\n", utils.HumanSize(out.Size))
1119
+					}
1116 1120
 				} else {
1117
-					fmt.Fprintf(w, "%s\n", utils.HumanSize(out.Size))
1121
+					fmt.Fprintln(w, out.ID)
1118 1122
 				}
1119
-			} else {
1120
-				fmt.Fprintln(w, out.ID)
1121 1123
 			}
1122 1124
 		}
1123 1125
 
... ...
@@ -284,7 +284,7 @@ func (srv *Server) Images(all bool, filter string) ([]APIImages, error) {
284 284
 	if err != nil {
285 285
 		return nil, err
286 286
 	}
287
-	outs := []APIImages{} //produce [] when empty instead of 'null'
287
+	lookup := make(map[string]APIImages)
288 288
 	for name, repository := range srv.runtime.repositories.Repositories {
289 289
 		if filter != "" {
290 290
 			if match, _ := path.Match(filter, name); !match {
... ...
@@ -292,23 +292,40 @@ func (srv *Server) Images(all bool, filter string) ([]APIImages, error) {
292 292
 			}
293 293
 		}
294 294
 		for tag, id := range repository {
295
-			var out APIImages
296 295
 			image, err := srv.runtime.graph.Get(id)
297 296
 			if err != nil {
298 297
 				log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
299 298
 				continue
300 299
 			}
301
-			delete(allImages, id)
302
-			out.Repository = name
303
-			out.Tag = tag
304
-			out.ID = image.ID
305
-			out.Created = image.Created.Unix()
306
-			out.Size = image.Size
307
-			out.VirtualSize = image.getParentsSize(0) + image.Size
308
-			outs = append(outs, out)
300
+
301
+			if out, exists := lookup[id]; exists {
302
+				out.RepoTags = append(out.RepoTags, fmt.Sprintf("%s:%s", name, tag))
303
+
304
+				lookup[id] = out
305
+			} else {
306
+				var out APIImages
307
+
308
+				delete(allImages, id)
309
+
310
+				out.ParentId = image.Parent
311
+				out.RepoTags = []string{fmt.Sprintf("%s:%s", name, tag)}
312
+				out.ID = image.ID
313
+				out.Created = image.Created.Unix()
314
+				out.Size = image.Size
315
+				out.VirtualSize = image.getParentsSize(0) + image.Size
316
+
317
+				lookup[id] = out
318
+			}
319
+
309 320
 		}
310 321
 	}
311
-	// Display images which aren't part of a
322
+
323
+	outs := make([]APIImages, 0, len(lookup))
324
+	for _, value := range lookup {
325
+		outs = append(outs, value)
326
+	}
327
+
328
+	// Display images which aren't part of a repository/tag
312 329
 	if filter == "" {
313 330
 		for _, image := range allImages {
314 331
 			var out APIImages
... ...
@@ -25,7 +25,7 @@ func (s *imageSorter) Less(i, j int) bool {
25 25
 // Sort []ApiImages by most recent creation date and tag name.
26 26
 func sortImagesByCreationAndTag(images []APIImages) {
27 27
 	creationAndTag := func(i1, i2 *APIImages) bool {
28
-		return i1.Created > i2.Created || (i1.Created == i2.Created && i2.Tag > i1.Tag)
28
+		return i1.Created > i2.Created
29 29
 	}
30 30
 
31 31
 	sorter := &imageSorter{