github.com/olljanat/moby@v1.13.1/cli/command/image/history.go (about)

     1  package image
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  	"text/tabwriter"
     8  	"time"
     9  
    10  	"golang.org/x/net/context"
    11  
    12  	"github.com/docker/docker/cli"
    13  	"github.com/docker/docker/cli/command"
    14  	"github.com/docker/docker/pkg/stringid"
    15  	"github.com/docker/docker/pkg/stringutils"
    16  	"github.com/docker/go-units"
    17  	"github.com/spf13/cobra"
    18  )
    19  
    20  type historyOptions struct {
    21  	image string
    22  
    23  	human   bool
    24  	quiet   bool
    25  	noTrunc bool
    26  }
    27  
    28  // NewHistoryCommand creates a new `docker history` command
    29  func NewHistoryCommand(dockerCli *command.DockerCli) *cobra.Command {
    30  	var opts historyOptions
    31  
    32  	cmd := &cobra.Command{
    33  		Use:   "history [OPTIONS] IMAGE",
    34  		Short: "Show the history of an image",
    35  		Args:  cli.ExactArgs(1),
    36  		RunE: func(cmd *cobra.Command, args []string) error {
    37  			opts.image = args[0]
    38  			return runHistory(dockerCli, opts)
    39  		},
    40  	}
    41  
    42  	flags := cmd.Flags()
    43  
    44  	flags.BoolVarP(&opts.human, "human", "H", true, "Print sizes and dates in human readable format")
    45  	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only show numeric IDs")
    46  	flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output")
    47  
    48  	return cmd
    49  }
    50  
    51  func runHistory(dockerCli *command.DockerCli, opts historyOptions) error {
    52  	ctx := context.Background()
    53  
    54  	history, err := dockerCli.Client().ImageHistory(ctx, opts.image)
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0)
    60  
    61  	if opts.quiet {
    62  		for _, entry := range history {
    63  			if opts.noTrunc {
    64  				fmt.Fprintf(w, "%s\n", entry.ID)
    65  			} else {
    66  				fmt.Fprintf(w, "%s\n", stringid.TruncateID(entry.ID))
    67  			}
    68  		}
    69  		w.Flush()
    70  		return nil
    71  	}
    72  
    73  	var imageID string
    74  	var createdBy string
    75  	var created string
    76  	var size string
    77  
    78  	fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT")
    79  	for _, entry := range history {
    80  		imageID = entry.ID
    81  		createdBy = strings.Replace(entry.CreatedBy, "\t", " ", -1)
    82  		if !opts.noTrunc {
    83  			createdBy = stringutils.Ellipsis(createdBy, 45)
    84  			imageID = stringid.TruncateID(entry.ID)
    85  		}
    86  
    87  		if opts.human {
    88  			created = units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))) + " ago"
    89  			size = units.HumanSizeWithPrecision(float64(entry.Size), 3)
    90  		} else {
    91  			created = time.Unix(entry.Created, 0).Format(time.RFC3339)
    92  			size = strconv.FormatInt(entry.Size, 10)
    93  		}
    94  
    95  		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", imageID, created, createdBy, size, entry.Comment)
    96  	}
    97  	w.Flush()
    98  	return nil
    99  }