From 0a3e85a43c5e206ae76e7bf251add4f718ebd7f5 Mon Sep 17 00:00:00 2001 From: Nick Adcock Date: Wed, 20 Nov 2019 15:07:52 +0000 Subject: [PATCH] Sort app image ls by created Sorts apps by created date (if available) when running `app image ls` with the latest created apps coming first. Signed-off-by: Nick Adcock --- e2e/images_test.go | 8 ++++---- internal/commands/image/list.go | 14 ++++++++++++++ internal/commands/image/list_test.go | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/e2e/images_test.go b/e2e/images_test.go index 632a939a6..a2871f3bb 100644 --- a/e2e/images_test.go +++ b/e2e/images_test.go @@ -26,7 +26,7 @@ func assertImageListOutput(t *testing.T, cmd icmd.Cmd, expected string) { stdout := result.Stdout() match, err := regexp.MatchString(expected, stdout) assert.NilError(t, err) - assert.Assert(t, match) + assert.Assert(t, match, expected, stdout) } func expectImageListOutput(t *testing.T, cmd icmd.Cmd, output string) { @@ -222,24 +222,24 @@ c-simple-app latest [a-f0-9]{12} simple cmd.Command = dockerCli.Command("app", "build", "--tag", "push-pull", filepath.Join("testdata", "push-pull")) icmd.RunCmd(cmd).Assert(t, icmd.Success) expectImageListOutput(t, cmd, `REPOSITORY TAG APP IMAGE ID APP NAME CREATED[ ]* +push-pull latest [a-f0-9]{12} push-pull [La-z0-9 ]+ ago[ ]* a-simple-app 0.1 [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* a-simple-app latest [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* b-simple-app 0.2 [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* b-simple-app latest [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* c-simple-app latest [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* -push-pull latest [a-f0-9]{12} push-pull [La-z0-9 ]+ ago[ ]* `) // can be tagged to an existing tag dockerAppImageTag("push-pull", "b-simple-app:0.2") icmd.RunCmd(cmd).Assert(t, icmd.Success) expectImageListOutput(t, cmd, `REPOSITORY TAG APP IMAGE ID APP NAME CREATED[ ]* +b-simple-app 0.2 [a-f0-9]{12} push-pull [La-z0-9 ]+ ago[ ]* +push-pull latest [a-f0-9]{12} push-pull [La-z0-9 ]+ ago[ ]* a-simple-app 0.1 [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* a-simple-app latest [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* -b-simple-app 0.2 [a-f0-9]{12} push-pull [La-z0-9 ]+ ago[ ]* b-simple-app latest [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* c-simple-app latest [a-f0-9]{12} simple [La-z0-9 ]+ ago[ ]* -push-pull latest [a-f0-9]{12} push-pull [La-z0-9 ]+ ago[ ]* `) }) } diff --git a/internal/commands/image/list.go b/internal/commands/image/list.go index 4ab51ad88..8fc479028 100644 --- a/internal/commands/image/list.go +++ b/internal/commands/image/list.go @@ -1,6 +1,7 @@ package image import ( + "sort" "time" "github.com/docker/app/internal/packager" @@ -60,6 +61,7 @@ func runList(dockerCli command.Cli, options imageListOption, bundleStore store.B Format: NewImageFormat(options.format, options.quiet, options.digests), } + sortImages(images) return Write(ctx, images) } @@ -92,6 +94,18 @@ func getImageID(bundle *relocated.Bundle, ref reference.Reference) (string, erro return stringid.TruncateID(id.String()), nil } +func sortImages(images []imageDesc) { + sort.SliceStable(images, func(i, j int) bool { + if images[i].Created.IsZero() { + return false + } + if images[j].Created.IsZero() { + return true + } + return images[i].Created.After(images[j].Created) + }) +} + type imageDesc struct { ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` diff --git a/internal/commands/image/list_test.go b/internal/commands/image/list_test.go index 3fe1e4d3e..4fbcde3f8 100644 --- a/internal/commands/image/list_test.go +++ b/internal/commands/image/list_test.go @@ -5,6 +5,7 @@ import ( "bytes" "fmt" "testing" + "time" "github.com/docker/app/internal/relocated" @@ -126,6 +127,22 @@ a855ac937f2e } } +func TestSortImages(t *testing.T) { + images := []imageDesc{ + {ID: "1", Created: time.Date(2016, time.August, 15, 0, 0, 0, 0, time.UTC)}, + {ID: "2"}, + {ID: "3"}, + {ID: "4", Created: time.Date(2018, time.August, 15, 0, 0, 0, 0, time.UTC)}, + {ID: "5", Created: time.Date(2017, time.August, 15, 0, 0, 0, 0, time.UTC)}, + } + sortImages(images) + assert.Equal(t, "4", images[0].ID) + assert.Equal(t, "5", images[1].ID) + assert.Equal(t, "1", images[2].ID) + assert.Equal(t, "2", images[3].ID) + assert.Equal(t, "3", images[4].ID) +} + func parseReference(t *testing.T, s string) reference.Reference { ref, err := reference.Parse(s) assert.NilError(t, err)