DockerCLI/cli/command/image/formatter_history.go

116 lines
2.9 KiB
Go
Raw Normal View History

package image
import (
"strconv"
"strings"
"time"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/pkg/stringid"
units "github.com/docker/go-units"
)
const (
defaultHistoryTableFormat = "table {{.ID}}\t{{.CreatedSince}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}"
nonHumanHistoryTableFormat = "table {{.ID}}\t{{.CreatedAt}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}"
historyIDHeader = "IMAGE"
createdByHeader = "CREATED BY"
commentHeader = "COMMENT"
)
// NewHistoryFormat returns a format for rendering an HistoryContext
func NewHistoryFormat(source string, quiet bool, human bool) formatter.Format {
linting: address else/if/elseif statements found by gocritic cli/command/formatter/tabwriter/tabwriter.go:579:10: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ cli/connhelper/connhelper.go:43:2: singleCaseSwitch: should rewrite switch statement to if statement (gocritic) switch scheme := u.Scheme; scheme { ^ cli/compose/loader/loader.go:666:10: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ opts/hosts_test.go:173:10: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ cli-plugins/manager/candidate_test.go:78:4: ifElseChain: rewrite if-else to switch statement (gocritic) if tc.err != "" { ^ cli/command/checkpoint/formatter.go:15:2: singleCaseSwitch: should rewrite switch statement to if statement (gocritic) switch source { ^ cli/command/image/formatter_history.go:25:2: singleCaseSwitch: should rewrite switch statement to if statement (gocritic) switch source { ^ cli/command/service/scale.go:107:2: ifElseChain: rewrite if-else to switch statement (gocritic) if serviceMode.Replicated != nil { ^ cli/command/service/update.go:804:9: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ cli/command/service/update.go:222:2: ifElseChain: rewrite if-else to switch statement (gocritic) if sendAuth { ^ cli/command/container/formatter_diff.go:17:2: singleCaseSwitch: should rewrite switch statement to if statement (gocritic) switch source { ^ cli/command/container/start.go:79:2: ifElseChain: rewrite if-else to switch statement (gocritic) if opts.Attach || opts.OpenStdin { ^ cli/command/container/utils.go:84:11: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ cli/command/container/exec_test.go:200:11: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ cli/command/container/logs_test.go:52:11: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ cli/command/container/opts_test.go:1014:10: elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic) } else { ^ cli/command/system/info.go:297:7: singleCaseSwitch: should rewrite switch statement to if statement (gocritic) switch o.Key { ^ cli/command/system/version.go:164:4: singleCaseSwitch: should rewrite switch statement to if statement (gocritic) switch component.Name { ^ cli/command/system/info_test.go:478:4: ifElseChain: rewrite if-else to switch statement (gocritic) if tc.expectedOut != "" { ^ Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-11-20 07:54:53 -05:00
if source == formatter.TableFormatKey {
switch {
case quiet:
return formatter.DefaultQuietFormat
case !human:
return nonHumanHistoryTableFormat
default:
return defaultHistoryTableFormat
}
}
return formatter.Format(source)
}
// HistoryWrite writes the context
func HistoryWrite(ctx formatter.Context, human bool, histories []image.HistoryResponseItem) error {
render := func(format func(subContext formatter.SubContext) error) error {
for _, history := range histories {
historyCtx := &historyContext{trunc: ctx.Trunc, h: history, human: human}
if err := format(historyCtx); err != nil {
return err
}
}
return nil
}
historyCtx := &historyContext{}
historyCtx.Header = formatter.SubHeaderContext{
"ID": historyIDHeader,
"CreatedSince": formatter.CreatedSinceHeader,
"CreatedAt": formatter.CreatedAtHeader,
"CreatedBy": createdByHeader,
"Size": formatter.SizeHeader,
"Comment": commentHeader,
}
return ctx.Write(historyCtx, render)
}
type historyContext struct {
formatter.HeaderContext
trunc bool
human bool
h image.HistoryResponseItem
}
func (c *historyContext) MarshalJSON() ([]byte, error) {
return formatter.MarshalJSON(c)
}
func (c *historyContext) ID() string {
if c.trunc {
return stringid.TruncateID(c.h.ID)
}
return c.h.ID
}
func (c *historyContext) CreatedAt() string {
return time.Unix(c.h.Created, 0).Format(time.RFC3339)
}
// epoch is the time before which created-at dates are not displayed with human units.
var epoch = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).Unix()
func (c *historyContext) CreatedSince() string {
if !c.human {
return c.CreatedAt()
}
if c.h.Created <= epoch {
return "N/A"
}
created := units.HumanDuration(time.Now().UTC().Sub(time.Unix(c.h.Created, 0)))
return created + " ago"
}
func (c *historyContext) CreatedBy() string {
linting: address assorted issues found by gocritic internal/test/builders/config.go:36:15: captLocal: `ID' should not be capitalized (gocritic) func ConfigID(ID string) func(config *swarm.Config) { ^ internal/test/builders/secret.go:45:15: captLocal: `ID' should not be capitalized (gocritic) func SecretID(ID string) func(secret *swarm.Secret) { ^ internal/test/builders/service.go:21:16: captLocal: `ID' should not be capitalized (gocritic) func ServiceID(ID string) func(*swarm.Service) { ^ cli/command/image/formatter_history.go:100:15: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.h.CreatedBy, "\t", " ", -1)` (gocritic) createdBy := strings.Replace(c.h.CreatedBy, "\t", " ", -1) ^ e2e/image/push_test.go:246:34: badCall: suspicious Join on 1 argument (gocritic) assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust")))) ^ e2e/image/push_test.go:313:34: badCall: suspicious Join on 1 argument (gocritic) assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust")))) ^ cli/config/configfile/file_test.go:185:2: assignOp: replace `c.GetAllCallCount = c.GetAllCallCount + 1` with `c.GetAllCallCount++` (gocritic) c.GetAllCallCount = c.GetAllCallCount + 1 ^ cli/command/context/inspect_test.go:20:58: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(si.MetadataPath, `\`, `\\`, -1)` (gocritic) expected = strings.Replace(expected, "<METADATA_PATH>", strings.Replace(si.MetadataPath, `\`, `\\`, -1), 1) ^ cli/command/context/inspect_test.go:21:53: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(si.TLSPath, `\`, `\\`, -1)` (gocritic) expected = strings.Replace(expected, "<TLS_PATH>", strings.Replace(si.TLSPath, `\`, `\\`, -1), 1) ^ cli/command/container/formatter_stats.go:119:46: captLocal: `Stats' should not be capitalized (gocritic) func statsFormatWrite(ctx formatter.Context, Stats []StatsEntry, osType string, trunc bool) error { ^ cli/command/container/stats_helpers.go:209:4: assignOp: replace `blkRead = blkRead + bioEntry.Value` with `blkRead += bioEntry.Value` (gocritic) blkRead = blkRead + bioEntry.Value ^ cli/command/container/stats_helpers.go:211:4: assignOp: replace `blkWrite = blkWrite + bioEntry.Value` with `blkWrite += bioEntry.Value` (gocritic) blkWrite = blkWrite + bioEntry.Value ^ cli/command/registry/formatter_search.go:67:10: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.s.Description, "\n", " ", -1)` (gocritic) desc := strings.Replace(c.s.Description, "\n", " ", -1) ^ cli/command/registry/formatter_search.go:68:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(desc, "\r", " ", -1)` (gocritic) desc = strings.Replace(desc, "\r", " ", -1) ^ cli/command/service/list_test.go:164:5: assignOp: replace `tc.doc = tc.doc + " with quiet"` with `tc.doc += " with quiet"` (gocritic) tc.doc = tc.doc + " with quiet" ^ cli/command/service/progress/progress.go:274:11: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(errMsg, "\n", " ", -1)` (gocritic) errMsg = strings.Replace(errMsg, "\n", " ", -1) ^ cli/manifest/store/store.go:153:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(fileName, "/", "_", -1)` (gocritic) return strings.Replace(fileName, "/", "_", -1) ^ cli/manifest/store/store.go:152:14: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(ref, ":", "-", -1)` (gocritic) fileName := strings.Replace(ref, ":", "-", -1) ^ cli/command/plugin/formatter.go:79:10: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(c.p.Config.Description, "\n", "", -1)` (gocritic) desc := strings.Replace(c.p.Config.Description, "\n", "", -1) ^ cli/command/plugin/formatter.go:80:9: wrapperFunc: use strings.ReplaceAll method in `strings.Replace(desc, "\r", "", -1)` (gocritic) desc = strings.Replace(desc, "\r", "", -1) ^ cli/compose/convert/service.go:642:23: captLocal: `DNS' should not be capitalized (gocritic) func convertDNSConfig(DNS []string, DNSSearch []string) *swarm.DNSConfig { ^ Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-11-20 07:30:05 -05:00
createdBy := strings.ReplaceAll(c.h.CreatedBy, "\t", " ")
if c.trunc {
return formatter.Ellipsis(createdBy, 45)
}
return createdBy
}
func (c *historyContext) Size() string {
if c.human {
return units.HumanSizeWithPrecision(float64(c.h.Size), 3)
}
return strconv.FormatInt(c.h.Size, 10)
}
func (c *historyContext) Comment() string {
return c.h.Comment
}