Skip to content

Commit cda6a69

Browse files
committed
ls: no-trunc opt
Signed-off-by: CrazyMax <[email protected]>
1 parent d826375 commit cda6a69

File tree

3 files changed

+148
-11
lines changed

3 files changed

+148
-11
lines changed

commands/ls.go

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ const (
3636
)
3737

3838
type lsOptions struct {
39-
format string
39+
format string
40+
noTrunc bool
4041
}
4142

4243
func runLs(dockerCli command.Cli, in lsOptions) error {
@@ -75,7 +76,7 @@ func runLs(dockerCli command.Cli, in lsOptions) error {
7576
return err
7677
}
7778

78-
if hasErrors, err := lsPrint(dockerCli, current, builders, in.format); err != nil {
79+
if hasErrors, err := lsPrint(dockerCli, current, builders, in); err != nil {
7980
return err
8081
} else if hasErrors {
8182
_, _ = fmt.Fprintf(dockerCli.Err(), "\n")
@@ -110,21 +111,23 @@ func lsCmd(dockerCli command.Cli) *cobra.Command {
110111

111112
flags := cmd.Flags()
112113
flags.StringVar(&options.format, "format", formatter.TableFormatKey, "Format the output")
114+
flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output")
113115

114116
// hide builder persistent flag for this command
115117
cobrautil.HideInheritedFlags(cmd, "builder")
116118

117119
return cmd
118120
}
119121

120-
func lsPrint(dockerCli command.Cli, current *store.NodeGroup, builders []*builder.Builder, format string) (hasErrors bool, _ error) {
121-
if format == formatter.TableFormatKey {
122-
format = lsDefaultTableFormat
122+
func lsPrint(dockerCli command.Cli, current *store.NodeGroup, builders []*builder.Builder, in lsOptions) (hasErrors bool, _ error) {
123+
if in.format == formatter.TableFormatKey {
124+
in.format = lsDefaultTableFormat
123125
}
124126

125127
ctx := formatter.Context{
126128
Output: dockerCli.Out(),
127-
Format: formatter.Format(format),
129+
Format: formatter.Format(in.format),
130+
Trunc: !in.noTrunc,
128131
}
129132

130133
sort.SliceStable(builders, func(i, j int) bool {
@@ -141,11 +144,12 @@ func lsPrint(dockerCli command.Cli, current *store.NodeGroup, builders []*builde
141144
render := func(format func(subContext formatter.SubContext) error) error {
142145
for _, b := range builders {
143146
if err := format(&lsContext{
147+
format: ctx.Format,
148+
trunc: ctx.Trunc,
144149
Builder: &lsBuilder{
145150
Builder: b,
146151
Current: b.Name == current.Name,
147152
},
148-
format: ctx.Format,
149153
}); err != nil {
150154
return err
151155
}
@@ -163,6 +167,7 @@ func lsPrint(dockerCli command.Cli, current *store.NodeGroup, builders []*builde
163167
}
164168
if err := format(&lsContext{
165169
format: ctx.Format,
170+
trunc: ctx.Trunc,
166171
Builder: &lsBuilder{
167172
Builder: b,
168173
Current: b.Name == current.Name,
@@ -199,6 +204,7 @@ type lsContext struct {
199204
Builder *lsBuilder
200205

201206
format formatter.Format
207+
trunc bool
202208
node builder.Node
203209
}
204210

@@ -264,7 +270,17 @@ func (c *lsContext) Platforms() string {
264270
if c.node.Name == "" {
265271
return ""
266272
}
267-
return strings.Join(platformutil.FormatInGroups(c.node.Node.Platforms, c.node.Platforms), ", ")
273+
platforms := platformutil.FormatInGroups(c.node.Node.Platforms, c.node.Platforms)
274+
if c.trunc && c.format.IsTable() {
275+
tplatforms := truncPlatforms(platforms, 4)
276+
left := len(platforms) - len(tplatforms)
277+
out := strings.Join(tplatforms, ", ")
278+
if left > 0 {
279+
out += fmt.Sprintf(", (+%d)", left)
280+
}
281+
return out
282+
}
283+
return strings.Join(platforms, ", ")
268284
}
269285

270286
func (c *lsContext) Error() string {
@@ -275,3 +291,51 @@ func (c *lsContext) Error() string {
275291
}
276292
return ""
277293
}
294+
295+
func truncPlatforms(platforms []string, max int) []string {
296+
majorPlatforms := map[string]struct{}{
297+
"linux/amd64": {},
298+
"linux/arm64": {},
299+
"linux/arm/v7": {},
300+
"linux/mips64": {},
301+
"linux/ppc64le": {},
302+
"linux/riscv64": {},
303+
"linux/s390x": {},
304+
}
305+
var res []string
306+
var left []string
307+
m := map[string]struct{}{}
308+
for _, p := range platforms {
309+
if len(res) >= max {
310+
break
311+
}
312+
pp := strings.TrimSuffix(p, "*")
313+
if _, ok := m[pp]; ok {
314+
continue
315+
}
316+
if _, ok := majorPlatforms[pp]; ok {
317+
res = append(res, p)
318+
m[pp] = struct{}{}
319+
} else {
320+
left = append(left, p)
321+
}
322+
}
323+
if len(left) > 0 && len(res) < max {
324+
cl := max - len(res)
325+
if cl > len(left) {
326+
cl = len(left)
327+
}
328+
res = append(res, left[:cl]...)
329+
}
330+
sort.SliceStable(res, func(i, j int) bool {
331+
ipref := strings.HasSuffix(res[i], "*")
332+
jpref := strings.HasSuffix(res[j], "*")
333+
if ipref && !jpref {
334+
return true
335+
} else if !ipref && jpref {
336+
return false
337+
}
338+
return i < j
339+
})
340+
return res
341+
}

commands/ls_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package commands
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestTruncPlatforms(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
platforms []string
13+
expected []string
14+
truncated bool
15+
max int
16+
}{
17+
{
18+
name: "arm64 preferred and emulated",
19+
platforms: []string{"linux/arm64*", "linux/amd64", "linux/amd64/v2", "linux/riscv64", "linux/ppc64le", "linux/s390x", "linux/386", "linux/mips64le", "linux/mips64", "linux/arm/v7", "linux/arm/v6"},
20+
expected: []string{"linux/arm64*", "linux/amd64", "linux/riscv64", "linux/ppc64le"},
21+
truncated: true,
22+
max: 4,
23+
},
24+
{
25+
name: "riscv64 preferred only",
26+
platforms: []string{"linux/riscv64*"},
27+
expected: []string{"linux/riscv64*"},
28+
max: 4,
29+
},
30+
{
31+
name: "amd64 no preferred and emulated",
32+
platforms: []string{"linux/amd64", "linux/amd64/v2", "linux/amd64/v3", "linux/386", "linux/arm64", "linux/riscv64", "linux/ppc64le", "linux/s390x", "linux/mips64le", "linux/mips64", "linux/arm/v7", "linux/arm/v6"},
33+
expected: []string{"linux/amd64", "linux/arm64", "linux/riscv64", "linux/ppc64le"},
34+
truncated: true,
35+
max: 4,
36+
},
37+
{
38+
name: "amd64 no preferred",
39+
platforms: []string{"linux/amd64", "linux/386"},
40+
expected: []string{"linux/amd64", "linux/386"},
41+
max: 4,
42+
},
43+
{
44+
name: "arm64 no preferred",
45+
platforms: []string{"linux/arm64", "linux/arm/v7", "linux/arm/v6"},
46+
expected: []string{"linux/arm64", "linux/arm/v7", "linux/arm/v6"},
47+
max: 4,
48+
},
49+
{
50+
name: "all preferred",
51+
platforms: []string{"darwin/arm64*", "linux/arm64*", "linux/arm/v5*", "linux/arm/v6*", "linux/arm/v7*", "windows/arm64*"},
52+
expected: []string{"linux/arm64*", "linux/arm/v7*", "darwin/arm64*", "linux/arm/v5*"},
53+
truncated: true,
54+
max: 4,
55+
},
56+
{
57+
name: "no major preferred",
58+
platforms: []string{"linux/amd64/v2*", "linux/arm/v6*", "linux/mips64le*", "linux/amd64", "linux/amd64/v3", "linux/386", "linux/arm64", "linux/riscv64", "linux/ppc64le", "linux/s390x", "linux/mips64", "linux/arm/v7"},
59+
expected: []string{"linux/amd64", "linux/arm64", "linux/riscv64", "linux/ppc64le"},
60+
truncated: true,
61+
max: 4,
62+
},
63+
}
64+
for _, tt := range tests {
65+
tt := tt
66+
t.Run(tt.name, func(t *testing.T) {
67+
tplatforms, truncated := truncPlatforms(tt.platforms, tt.max)
68+
assert.Equal(t, tt.expected, tplatforms)
69+
assert.Equal(t, tt.truncated, truncated)
70+
})
71+
}
72+
}

docs/reference/buildx_ls.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ List builder instances
99

1010
### Options
1111

12-
| Name | Type | Default | Description |
13-
|:----------------------|:---------|:--------|:------------------|
14-
| [`--format`](#format) | `string` | `table` | Format the output |
12+
| Name | Type | Default | Description |
13+
|:----------------------|:---------|:--------|:----------------------|
14+
| [`--format`](#format) | `string` | `table` | Format the output |
15+
| `--no-trunc` | | | Don't truncate output |
1516

1617

1718
<!---MARKER_GEN_END-->

0 commit comments

Comments
 (0)