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