diff --git a/api/client/commands.go b/api/client/commands.go index bf49939b5b..e45a65ff86 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -9,7 +9,6 @@ func (cli *DockerCli) Command(name string) func(...string) error { "cp": cli.CmdCp, "events": cli.CmdEvents, "exec": cli.CmdExec, - "history": cli.CmdHistory, "images": cli.CmdImages, "import": cli.CmdImport, "info": cli.CmdInfo, diff --git a/api/client/history.go b/api/client/history.go deleted file mode 100644 index 25bb41571f..0000000000 --- a/api/client/history.go +++ /dev/null @@ -1,76 +0,0 @@ -package client - -import ( - "fmt" - "strconv" - "strings" - "text/tabwriter" - "time" - - "golang.org/x/net/context" - - Cli "github.com/docker/docker/cli" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/go-units" -) - -// CmdHistory shows the history of an image. -// -// Usage: docker history [OPTIONS] IMAGE -func (cli *DockerCli) CmdHistory(args ...string) error { - cmd := Cli.Subcmd("history", []string{"IMAGE"}, Cli.DockerCommands["history"].Description, true) - human := cmd.Bool([]string{"H", "-human"}, true, "Print sizes and dates in human readable format") - quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") - noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Don't truncate output") - cmd.Require(flag.Exact, 1) - - cmd.ParseFlags(args, true) - - history, err := cli.client.ImageHistory(context.Background(), cmd.Arg(0)) - if err != nil { - return err - } - - w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - - if *quiet { - for _, entry := range history { - if *noTrunc { - fmt.Fprintf(w, "%s\n", entry.ID) - } else { - fmt.Fprintf(w, "%s\n", stringid.TruncateID(entry.ID)) - } - } - w.Flush() - return nil - } - - var imageID string - var createdBy string - var created string - var size string - - fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT") - for _, entry := range history { - imageID = entry.ID - createdBy = strings.Replace(entry.CreatedBy, "\t", " ", -1) - if *noTrunc == false { - createdBy = stringutils.Truncate(createdBy, 45) - imageID = stringid.TruncateID(entry.ID) - } - - if *human { - created = units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))) + " ago" - size = units.HumanSize(float64(entry.Size)) - } else { - created = time.Unix(entry.Created, 0).Format(time.RFC3339) - size = strconv.FormatInt(entry.Size, 10) - } - - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", imageID, created, createdBy, size, entry.Comment) - } - w.Flush() - return nil -} diff --git a/api/client/image/history.go b/api/client/image/history.go new file mode 100644 index 0000000000..abf2a0bb3b --- /dev/null +++ b/api/client/image/history.go @@ -0,0 +1,99 @@ +package image + +import ( + "fmt" + "strconv" + "strings" + "text/tabwriter" + "time" + + "golang.org/x/net/context" + + "github.com/docker/docker/api/client" + "github.com/docker/docker/cli" + "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/pkg/stringutils" + "github.com/docker/go-units" + "github.com/spf13/cobra" +) + +type historyOptions struct { + image string + + human bool + quiet bool + noTrunc bool +} + +// NewHistoryCommand create a new `docker history` command +func NewHistoryCommand(dockerCli *client.DockerCli) *cobra.Command { + var opts historyOptions + + cmd := &cobra.Command{ + Use: "history [OPTIONS] IMAGE", + Short: "Show the history of an image", + Args: cli.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + opts.image = args[0] + return runHistory(dockerCli, opts) + }, + } + + flags := cmd.Flags() + + flags.BoolVarP(&opts.human, "human", "H", true, "Print sizes and dates in human readable format") + flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only show numeric IDs") + flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output") + + return cmd +} + +func runHistory(dockerCli *client.DockerCli, opts historyOptions) error { + ctx := context.Background() + + history, err := dockerCli.Client().ImageHistory(ctx, opts.image) + if err != nil { + return err + } + + w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) + + if opts.quiet { + for _, entry := range history { + if opts.noTrunc { + fmt.Fprintf(w, "%s\n", entry.ID) + } else { + fmt.Fprintf(w, "%s\n", stringid.TruncateID(entry.ID)) + } + } + w.Flush() + return nil + } + + var imageID string + var createdBy string + var created string + var size string + + fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT") + for _, entry := range history { + imageID = entry.ID + createdBy = strings.Replace(entry.CreatedBy, "\t", " ", -1) + if opts.noTrunc == false { + createdBy = stringutils.Truncate(createdBy, 45) + imageID = stringid.TruncateID(entry.ID) + } + + if opts.human { + created = units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))) + " ago" + size = units.HumanSize(float64(entry.Size)) + } else { + created = time.Unix(entry.Created, 0).Format(time.RFC3339) + size = strconv.FormatInt(entry.Size, 10) + } + + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", imageID, created, createdBy, size, entry.Comment) + } + w.Flush() + return nil +} diff --git a/cli/cobraadaptor/adaptor.go b/cli/cobraadaptor/adaptor.go index ee51435b87..f1d97002c6 100644 --- a/cli/cobraadaptor/adaptor.go +++ b/cli/cobraadaptor/adaptor.go @@ -43,6 +43,7 @@ func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor { container.NewStopCommand(dockerCli), container.NewUnpauseCommand(dockerCli), container.NewWaitCommand(dockerCli), + image.NewHistoryCommand(dockerCli), image.NewRemoveCommand(dockerCli), image.NewSearchCommand(dockerCli), network.NewNetworkCommand(dockerCli), diff --git a/cli/usage.go b/cli/usage.go index 23c357e1cf..b9563cb154 100644 --- a/cli/usage.go +++ b/cli/usage.go @@ -14,7 +14,6 @@ var DockerCommandUsage = []Command{ {"cp", "Copy files/folders between a container and the local filesystem"}, {"events", "Get real time events from the server"}, {"exec", "Run a command in a running container"}, - {"history", "Show the history of an image"}, {"images", "List images"}, {"import", "Import the contents from a tarball to create a filesystem image"}, {"info", "Display system-wide information"},