Browse Source

'docker images' doesn't show all anonymous images by default - only anonymous heads

Solomon Hykes 12 years ago
parent
commit
d301c7b98c
2 changed files with 51 additions and 5 deletions
  1. 8 1
      commands.go
  2. 43 4
      graph.go

+ 8 - 1
commands.go

@@ -493,6 +493,7 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri
 	cmd := rcli.Subcmd(stdout, "images", "[OPTIONS] [NAME]", "List images")
 	//limit := cmd.Int("l", 0, "Only show the N most recent versions of each image")
 	quiet := cmd.Bool("q", false, "only show numeric IDs")
+	fl_a := cmd.Bool("a", false, "show all images")
 	if err := cmd.Parse(args); err != nil {
 		return nil
 	}
@@ -508,7 +509,13 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri
 	if !*quiet {
 		fmt.Fprintf(w, "REPOSITORY\tTAG\tID\tCREATED\tPARENT\n")
 	}
-	allImages, err := srv.runtime.graph.Map()
+	var allImages map[string]*Image
+	var err error
+	if *fl_a {
+		allImages, err = srv.runtime.graph.Map()
+	} else {
+		allImages, err = srv.runtime.graph.Heads()
+	}
 	if err != nil {
 		return err
 	}

+ 43 - 4
graph.go

@@ -141,20 +141,59 @@ func (graph *Graph) Map() (map[string]*Image, error) {
 }
 
 func (graph *Graph) All() ([]*Image, error) {
+	var images []*Image
+	err := graph.WalkAll(func(image *Image) {
+		images = append(images, image)
+	})
+	return images, err
+}
+
+func (graph *Graph) WalkAll(handler func(*Image)) error {
 	files, err := ioutil.ReadDir(graph.Root)
 	if err != nil {
-		return nil, err
+		return err
 	}
-	var images []*Image
 	for _, st := range files {
 		if img, err := graph.Get(st.Name()); err != nil {
 			// Skip image
 			continue
+		} else if handler != nil {
+			handler(img)
+		}
+	}
+	return nil
+}
+
+func (graph *Graph) ByParent() (map[string][]*Image, error) {
+	byParent := make(map[string][]*Image)
+	err := graph.WalkAll(func(image *Image) {
+		image, err := graph.Get(image.Parent)
+		if err != nil {
+			return
+		}
+		if children, exists := byParent[image.Parent]; exists {
+			byParent[image.Parent] = []*Image{image}
 		} else {
-			images = append(images, img)
+			byParent[image.Parent] = append(children, image)
 		}
+	})
+	return byParent, err
+}
+
+func (graph *Graph) Heads() (map[string]*Image, error) {
+	heads := make(map[string]*Image)
+	byParent, err := graph.ByParent()
+	if err != nil {
+		return nil, err
 	}
-	return images, nil
+	err = graph.WalkAll(func(image *Image) {
+		// If it's not in the byParent lookup table, then
+		// it's not a parent -> so it's a head!
+		if _, exists := byParent[image.Id]; !exists {
+			heads[image.Id] = image
+		}
+	})
+	return heads, err
 }
 
 func (graph *Graph) imageRoot(id string) string {