Skip to content

Commit 44648be

Browse files
committed
image/list: Show collapsed tree by default
Use the new tree view by default and only fallback if format or old view-related options are used. The expanded view is shown when `--tree` is passed. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
1 parent 513ee76 commit 44648be

2 files changed

Lines changed: 55 additions & 29 deletions

File tree

cli/command/image/list.go

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,9 @@ func runImages(ctx context.Context, dockerCLI command.Cli, options imagesOptions
8989
filters.Add("reference", options.matchName)
9090
}
9191

92-
if options.tree {
93-
if options.quiet {
94-
return errors.New("--quiet is not yet supported with --tree")
95-
}
96-
if options.noTrunc {
97-
return errors.New("--no-trunc is not yet supported with --tree")
98-
}
99-
if options.showDigests {
100-
return errors.New("--show-digest is not yet supported with --tree")
101-
}
102-
if options.format != "" {
103-
return errors.New("--format is not yet supported with --tree")
104-
}
92+
useTree, err := shouldUseTree(options)
93+
if err != nil {
94+
return err
10595
}
10696

10797
listOpts := client.ImageListOptions{
@@ -114,18 +104,20 @@ func runImages(ctx context.Context, dockerCLI command.Cli, options imagesOptions
114104
if err != nil {
115105
return err
116106
}
107+
117108
images := res.Items
118109
if !options.all {
119110
if _, ok := filters["dangling"]; ok {
120111
images = slices.DeleteFunc(images, isDangling)
121112
}
122113
}
123114

124-
if options.tree {
115+
if useTree {
125116
return runTree(ctx, dockerCLI, treeOptions{
126-
images: images,
127-
all: options.all,
128-
filters: filters,
117+
images: images,
118+
all: options.all,
119+
filters: filters,
120+
expanded: options.tree,
129121
})
130122
}
131123

@@ -155,6 +147,34 @@ func runImages(ctx context.Context, dockerCLI command.Cli, options imagesOptions
155147
return nil
156148
}
157149

150+
func shouldUseTree(options imagesOptions) (bool, error) {
151+
if options.quiet {
152+
if options.tree {
153+
return false, errors.New("--quiet is not yet supported with --tree")
154+
}
155+
return false, nil
156+
}
157+
if options.noTrunc {
158+
if options.tree {
159+
return false, errors.New("--no-trunc is not yet supported with --tree")
160+
}
161+
return false, nil
162+
}
163+
if options.showDigests {
164+
if options.tree {
165+
return false, errors.New("--show-digest is not yet supported with --tree")
166+
}
167+
return false, nil
168+
}
169+
if options.format != "" {
170+
if options.tree {
171+
return false, errors.New("--format is not yet supported with --tree")
172+
}
173+
return false, nil
174+
}
175+
return true, nil
176+
}
177+
158178
// isDangling is a copy of [formatter.isDangling].
159179
func isDangling(img image.Summary) bool {
160180
if len(img.RepoTags) == 0 && len(img.RepoDigests) == 0 {

cli/command/image/tree.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ import (
2323
)
2424

2525
type treeOptions struct {
26-
images []imagetypes.Summary
27-
all bool
28-
filters client.Filters
26+
images []imagetypes.Summary
27+
all bool
28+
filters client.Filters
29+
expanded bool
2930
}
3031

3132
type treeView struct {
@@ -47,7 +48,7 @@ func runTree(ctx context.Context, dockerCLI command.Cli, opts treeOptions) error
4748
if ctx.Err() != nil {
4849
return ctx.Err()
4950
}
50-
details := imageDetails{
51+
topDetails := imageDetails{
5152
ID: img.ID,
5253
DiskUsage: units.HumanSizeWithPrecision(float64(img.Size), 3),
5354
InUse: img.Containers > 0,
@@ -66,33 +67,38 @@ func runTree(ctx context.Context, dockerCLI command.Cli, opts treeOptions) error
6667
continue
6768
}
6869

70+
inUse := len(im.ImageData.Containers) > 0
71+
if inUse {
72+
// Mark top-level parent image as used if any of its subimages are used.
73+
topDetails.InUse = true
74+
}
75+
76+
if !opts.expanded {
77+
continue
78+
}
79+
6980
sub := subImage{
7081
Platform: platforms.Format(im.ImageData.Platform),
7182
Available: im.Available,
7283
Details: imageDetails{
7384
ID: im.ID,
7485
DiskUsage: units.HumanSizeWithPrecision(float64(im.Size.Total), 3),
75-
InUse: len(im.ImageData.Containers) > 0,
86+
InUse: inUse,
7687
ContentSize: units.HumanSizeWithPrecision(float64(im.Size.Content), 3),
7788
},
7889
}
7990

80-
if sub.Details.InUse {
81-
// Mark top-level parent image as used if any of its subimages are used.
82-
details.InUse = true
83-
}
84-
8591
children = append(children, sub)
8692

8793
// Add extra spacing between images if there's at least one entry with children.
8894
view.imageSpacing = true
8995
}
9096

91-
details.ContentSize = units.HumanSizeWithPrecision(float64(totalContent), 3)
97+
topDetails.ContentSize = units.HumanSizeWithPrecision(float64(totalContent), 3)
9298

9399
view.images = append(view.images, topImage{
94100
Names: img.RepoTags,
95-
Details: details,
101+
Details: topDetails,
96102
Children: children,
97103
created: img.Created,
98104
})

0 commit comments

Comments
 (0)