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