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