github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/daemon/image_history.go (about)

     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.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  }