Skip to content
3 changes: 2 additions & 1 deletion cli-plugins/manager/cobra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package manager
import (
"os"
"path/filepath"
"slices"
"sync"
"testing"

Expand Down Expand Up @@ -45,7 +46,7 @@ func TestPluginStubCompletionRestoresOSArgs(t *testing.T) {
t.Cleanup(func() { os.Args = savedArgs })

originalArgs := []string{"docker", "image", "ls"}
os.Args = append([]string(nil), originalArgs...)
os.Args = slices.Clone(originalArgs)

_, directive := cmd.ValidArgsFunction(cmd, []string{"--all"}, "alp")
assert.Equal(t, directive, cobra.ShellCompDirectiveError)
Expand Down
7 changes: 4 additions & 3 deletions cli/command/completion/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package completion
import (
"context"
"errors"
"sort"
"testing"

"github.com/google/go-cmp/cmp/cmpopts"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/image"
"github.com/moby/moby/api/types/network"
Expand Down Expand Up @@ -177,9 +177,10 @@ func TestCompleteEnvVarNames(t *testing.T) {
values, directives := EnvVarNames()(nil, nil, "")
assert.Check(t, is.Equal(directives&cobra.ShellCompDirectiveNoFileComp, cobra.ShellCompDirectiveNoFileComp), "Should not perform file completion")

sort.Strings(values)
expected := []string{"ENV_A", "ENV_B"}
assert.Check(t, is.DeepEqual(values, expected))
assert.Check(t, is.DeepEqual(values, expected, cmpopts.SortSlices(func(a, b string) bool {
return a < b
})))
}

func TestCompleteFileNames(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions cli/command/container/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import (
"os"
"path/filepath"
"runtime"
"sort"
"strings"
"testing"

"github.com/docker/cli/cli"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/system"
"github.com/moby/moby/client"
Expand Down Expand Up @@ -284,12 +284,12 @@ func TestCreateContainerWithProxyConfig(t *testing.T) {
"ALL_PROXY=allProxy",
"all_proxy=allProxy",
}
sort.Strings(expected)

fakeCLI := test.NewFakeCli(&fakeClient{
createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) {
sort.Strings(options.Config.Env)
assert.DeepEqual(t, options.Config.Env, expected)
assert.DeepEqual(t, options.Config.Env, expected, cmpopts.SortSlices(func(a, b string) bool {
return a < b
}))
return client.ContainerCreateResult{}, nil
},
})
Expand Down
7 changes: 4 additions & 3 deletions cli/command/container/restart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"context"
"errors"
"io"
"sort"
"sync"
"testing"

"github.com/docker/cli/internal/test"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/moby/moby/client"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
Expand Down Expand Up @@ -87,8 +87,9 @@ func TestRestart(t *testing.T) {
} else {
assert.Check(t, is.Nil(err))
}
sort.Strings(restarted)
assert.Check(t, is.DeepEqual(restarted, tc.restarted))
assert.Check(t, is.DeepEqual(restarted, tc.restarted, cmpopts.SortSlices(func(a, b string) bool {
return a < b
})))
})
}
}
8 changes: 5 additions & 3 deletions cli/command/container/rm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"context"
"errors"
"io"
"sort"
"sync"
"testing"

"github.com/docker/cli/internal/test"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/moby/moby/client"
"gotest.tools/v3/assert"
)
Expand Down Expand Up @@ -53,8 +53,10 @@ func TestRemoveForce(t *testing.T) {
assert.NilError(t, err)
}
assert.Equal(t, cli.ErrBuffer().String(), "")
sort.Strings(removed)
assert.DeepEqual(t, removed, []string{"mycontainer", "nosuchcontainer"})
expected := []string{"mycontainer", "nosuchcontainer"}
assert.DeepEqual(t, removed, expected, cmpopts.SortSlices(func(a, b string) bool {
return a < b
}))
})
}
}
7 changes: 4 additions & 3 deletions cli/command/container/stop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"context"
"errors"
"io"
"sort"
"sync"
"testing"

"github.com/docker/cli/internal/test"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/moby/moby/client"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
Expand Down Expand Up @@ -88,8 +88,9 @@ func TestStop(t *testing.T) {
} else {
assert.Check(t, is.Nil(err))
}
sort.Strings(stopped)
assert.Check(t, is.DeepEqual(stopped, tc.stopped))
assert.Check(t, is.DeepEqual(stopped, tc.stopped, cmpopts.SortSlices(func(a, b string) bool {
return a < b
})))
})
}
}
29 changes: 16 additions & 13 deletions cli/command/formatter/buildcache.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26

package formatter

import (
"sort"
"slices"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -52,20 +55,20 @@ shared: {{.Shared}}
}

func buildCacheSort(buildCache []build.CacheRecord) {
sort.Slice(buildCache, func(i, j int) bool {
lui, luj := buildCache[i].LastUsedAt, buildCache[j].LastUsedAt
slices.SortFunc(buildCache, func(a, b build.CacheRecord) int {
switch {
case lui == nil && luj == nil:
return strings.Compare(buildCache[i].ID, buildCache[j].ID) < 0
case lui == nil:
return true
case luj == nil:
return false
case lui.Equal(*luj):
return strings.Compare(buildCache[i].ID, buildCache[j].ID) < 0
default:
return lui.Before(*luj)
case a.LastUsedAt == nil && b.LastUsedAt == nil:
return strings.Compare(a.ID, b.ID)
case a.LastUsedAt == nil:
return -1
case b.LastUsedAt == nil:
return 1
}

if c := a.LastUsedAt.Compare(*b.LastUsedAt); c != 0 {
return c
}
return strings.Compare(a.ID, b.ID)
})
}

Expand Down
32 changes: 13 additions & 19 deletions cli/command/formatter/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
package formatter

import (
"cmp"
"fmt"
"net"
"sort"
"slices"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -295,7 +296,7 @@ func (c *ContainerContext) Labels() string {
for k, v := range c.c.Labels {
joinLabels = append(joinLabels, k+"="+v)
}
sort.Strings(joinLabels)
slices.Sort(joinLabels)
return strings.Join(joinLabels, ",")
}

Expand Down Expand Up @@ -395,9 +396,7 @@ func DisplayablePorts(ports []container.PortSummary) string {
var result []string
var hostMappings []string
var groupMapKeys []string
sort.Slice(ports, func(i, j int) bool {
return comparePorts(ports[i], ports[j])
})
slices.SortFunc(ports, comparePorts)

for _, port := range ports {
current := port.PrivatePort
Expand Down Expand Up @@ -452,18 +451,13 @@ func formGroup(key string, start, last uint16) string {
return group + "/" + groupType
}

func comparePorts(i, j container.PortSummary) bool {
if i.PrivatePort != j.PrivatePort {
return i.PrivatePort < j.PrivatePort
}

if i.IP != j.IP {
return i.IP.Less(j.IP)
}

if i.PublicPort != j.PublicPort {
return i.PublicPort < j.PublicPort
}

return i.Type < j.Type
// comparePorts compares ports by private port, IP address, public port,
// and protocol, in that order.
func comparePorts(a, b container.PortSummary) int {
return cmp.Or(
cmp.Compare(a.PrivatePort, b.PrivatePort),
a.IP.Compare(b.IP),
cmp.Compare(a.PublicPort, b.PublicPort),
cmp.Compare(a.Type, b.Type),
)
}
6 changes: 5 additions & 1 deletion cli/command/image/build/internal/git/gitutils.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26

package git

import (
Expand All @@ -7,6 +10,7 @@ import (
"os"
"os/exec"
"path/filepath"
"slices"
"strings"

"github.com/moby/sys/symlink"
Expand Down Expand Up @@ -202,7 +206,7 @@ func (repo gitRepo) checkout(root string) (string, error) {
}

func (repo gitRepo) gitWithinDir(dir string, args ...string) ([]byte, error) {
args = append([]string{"-c", "protocol.file.allow=never"}, args...) // Block sneaky repositories from using repos from the filesystem as submodules.
args = slices.Concat([]string{"-c", "protocol.file.allow=never"}, args) // Block sneaky repositories from using repos from the filesystem as submodules.
cmd := exec.Command("git", args...)
cmd.Dir = dir
// Disable unsafe remote protocols.
Expand Down
4 changes: 2 additions & 2 deletions cli/command/image/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"io"
"os"
"path/filepath"
"sort"
"slices"
"testing"

"github.com/docker/cli/cli/streams"
Expand Down Expand Up @@ -211,6 +211,6 @@ func (f *fakeBuild) filenames(t *testing.T) []string {
for _, header := range h {
names = append(names, header.Name)
}
sort.Strings(names)
slices.Sort(names)
return names
}
8 changes: 5 additions & 3 deletions cli/command/image/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,11 @@ func TestRunPushRespectsNoColorForAuxNotes(t *testing.T) {
SelectedManifest: ocispec.Descriptor{Digest: "sha256:2222222222222222222222222222222222222222222222222222222222222222"},
})
assert.NilError(t, err)
line := append([]byte(`{"aux":`), aux...)
line = append(line, '}', '\n')
return fakeStreamResult{ReadCloser: io.NopCloser(bytes.NewReader(line))}, nil
var buf bytes.Buffer
buf.WriteString(`{"aux":`)
buf.Write(aux)
buf.WriteString("}\n")
return fakeStreamResult{ReadCloser: io.NopCloser(&buf)}, nil
},
})
cli.Out().SetIsTerminal(true)
Expand Down
22 changes: 13 additions & 9 deletions cli/command/service/formatter.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26

package service

import (
"cmp"
"errors"
"fmt"
"slices"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -775,17 +780,16 @@ func (c *serviceContext) Ports() string {
return ""
}

pr := portRange{}
ports := []string{}

servicePorts := c.service.Endpoint.Ports
sort.Slice(servicePorts, func(i, j int) bool {
if servicePorts[i].Protocol == servicePorts[j].Protocol {
return servicePorts[i].PublishedPort < servicePorts[j].PublishedPort
}
return servicePorts[i].Protocol < servicePorts[j].Protocol
// Sort by protocol first, then by published port.
slices.SortFunc(c.service.Endpoint.Ports, func(a, b swarm.PortConfig) int {
return cmp.Or(
cmp.Compare(a.Protocol, b.Protocol),
cmp.Compare(a.PublishedPort, b.PublishedPort),
)
})

var pr portRange
var ports []string
for _, p := range c.service.Endpoint.Ports {
if p.PublishMode == swarm.PortConfigPublishModeIngress {
prIsRange := pr.tEnd != pr.tStart
Expand Down
7 changes: 5 additions & 2 deletions cli/command/service/logs.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26

package service

import (
Expand All @@ -6,7 +9,7 @@ import (
"errors"
"fmt"
"io"
"sort"
"slices"
"strconv"
"strings"

Expand Down Expand Up @@ -314,7 +317,7 @@ func (lw *logWriter) Write(buf []byte) (int, error) {
d = append(d, k+"="+details[k])
}
// then sort em
sort.Strings(d)
slices.Sort(d)
// then join and append
output = append(output, []byte(strings.Join(d, ","))...)
output = append(output, ' ')
Expand Down
Loading