Tizen_4.0 base
[platform/upstream/docker-engine.git] / daemon / image_history.go
1 package daemon
2
3 import (
4         "fmt"
5         "runtime"
6         "time"
7
8         "github.com/docker/distribution/reference"
9         "github.com/docker/docker/api/types/image"
10         "github.com/docker/docker/layer"
11 )
12
13 // ImageHistory returns a slice of ImageHistory structures for the specified image
14 // name by walking the image lineage.
15 func (daemon *Daemon) ImageHistory(name string) ([]*image.HistoryResponseItem, error) {
16         start := time.Now()
17         img, err := daemon.GetImage(name)
18         if err != nil {
19                 return nil, err
20         }
21
22         // If the image OS isn't set, assume it's the host OS
23         platform := img.OS
24         if platform == "" {
25                 platform = runtime.GOOS
26         }
27
28         history := []*image.HistoryResponseItem{}
29
30         layerCounter := 0
31         rootFS := *img.RootFS
32         rootFS.DiffIDs = nil
33
34         for _, h := range img.History {
35                 var layerSize int64
36
37                 if !h.EmptyLayer {
38                         if len(img.RootFS.DiffIDs) <= layerCounter {
39                                 return nil, fmt.Errorf("too many non-empty layers in History section")
40                         }
41
42                         rootFS.Append(img.RootFS.DiffIDs[layerCounter])
43                         l, err := daemon.stores[platform].layerStore.Get(rootFS.ChainID())
44                         if err != nil {
45                                 return nil, err
46                         }
47                         layerSize, err = l.DiffSize()
48                         layer.ReleaseAndLog(daemon.stores[platform].layerStore, l)
49                         if err != nil {
50                                 return nil, err
51                         }
52
53                         layerCounter++
54                 }
55
56                 history = append([]*image.HistoryResponseItem{{
57                         ID:        "<missing>",
58                         Created:   h.Created.Unix(),
59                         CreatedBy: h.CreatedBy,
60                         Comment:   h.Comment,
61                         Size:      layerSize,
62                 }}, history...)
63         }
64
65         // Fill in image IDs and tags
66         histImg := img
67         id := img.ID()
68         for _, h := range history {
69                 h.ID = id.String()
70
71                 var tags []string
72                 for _, r := range daemon.stores[platform].referenceStore.References(id.Digest()) {
73                         if _, ok := r.(reference.NamedTagged); ok {
74                                 tags = append(tags, reference.FamiliarString(r))
75                         }
76                 }
77
78                 h.Tags = tags
79
80                 id = histImg.Parent
81                 if id == "" {
82                         break
83                 }
84                 histImg, err = daemon.GetImage(id.String())
85                 if err != nil {
86                         break
87                 }
88         }
89         imageActions.WithValues("history").UpdateSince(start)
90         return history, nil
91 }