history.go 2.3 KB

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