Bläddra i källkod

refactor: use slices package for sort (#10132)

The sort package is still used in places that were not trivial to
change. Since Go 1.21 slices package can be uswed for sort. See
https://go.dev/doc/go1.21#slices

### Purpose

Make some progress with the migration to a more up-to-date syntax.
Marcel Meyer 4 månader sedan
förälder
incheckning
48b757cac1

+ 4 - 3
cmd/infra/stcrashreceiver/diskstore.go

@@ -8,6 +8,7 @@ package main
 
 import (
 	"bytes"
+	"cmp"
 	"compress/gzip"
 	"context"
 	"io"
@@ -15,7 +16,7 @@ import (
 	"math"
 	"os"
 	"path/filepath"
-	"sort"
+	"slices"
 	"time"
 )
 
@@ -177,8 +178,8 @@ func (d *diskStore) inventory() error {
 		})
 		return nil
 	})
-	sort.Slice(d.currentFiles, func(i, j int) bool {
-		return d.currentFiles[i].mtime < d.currentFiles[j].mtime
+	slices.SortFunc(d.currentFiles, func(a, b currentFile) int {
+		return cmp.Compare(a.mtime, b.mtime)
 	})
 	var oldest time.Duration
 	if len(d.currentFiles) > 0 {

+ 4 - 3
cmd/syncthing/cli/index_dumpsize.go

@@ -7,9 +7,10 @@
 package cli
 
 import (
+	"cmp"
 	"encoding/binary"
 	"fmt"
-	"sort"
+	"slices"
 
 	"github.com/syncthing/syncthing/lib/db"
 )
@@ -77,8 +78,8 @@ func indexDumpSize() error {
 		elems = append(elems, ele)
 	}
 
-	sort.Slice(elems, func(i, j int) bool {
-		return elems[i].size > elems[j].size
+	slices.SortFunc(elems, func(a, b sizedElement) int {
+		return cmp.Compare(b.size, a.size)
 	})
 	for _, ele := range elems {
 		fmt.Println(ele.key, ele.size)

+ 6 - 5
cmd/syncthing/cli/index_idxck.go

@@ -8,10 +8,11 @@ package cli
 
 import (
 	"bytes"
+	"cmp"
 	"encoding/binary"
 	"errors"
 	"fmt"
-	"sort"
+	"slices"
 
 	"google.golang.org/protobuf/proto"
 
@@ -207,11 +208,11 @@ func indexCheck() (err error) {
 
 	// Aggregate the ranges of missing sequence entries, print them
 
-	sort.Slice(missingSeq, func(a, b int) bool {
-		if missingSeq[a].folder != missingSeq[b].folder {
-			return missingSeq[a].folder < missingSeq[b].folder
+	slices.SortFunc(missingSeq, func(a, b sequenceKey) int {
+		if a.folder != b.folder {
+			return cmp.Compare(a.folder, b.folder)
 		}
-		return missingSeq[a].sequence < missingSeq[b].sequence
+		return cmp.Compare(a.sequence, b.sequence)
 	})
 
 	var folder uint32

+ 2 - 2
cmd/syncthing/main.go

@@ -23,7 +23,7 @@ import (
 	"path/filepath"
 	"regexp"
 	"runtime/pprof"
-	"sort"
+	"slices"
 	"strconv"
 	"strings"
 	"syscall"
@@ -443,7 +443,7 @@ func debugFacilities() string {
 			maxLen = len(name)
 		}
 	}
-	sort.Strings(names)
+	slices.Sort(names)
 
 	// Format the choices
 	b := new(bytes.Buffer)

+ 8 - 7
lib/api/api.go

@@ -8,6 +8,7 @@ package api
 
 import (
 	"bytes"
+	"cmp"
 	"context"
 	"crypto/tls"
 	"crypto/x509"
@@ -24,7 +25,7 @@ import (
 	"reflect"
 	"runtime"
 	"runtime/pprof"
-	"sort"
+	"slices"
 	"strconv"
 	"strings"
 	"time"
@@ -750,7 +751,7 @@ func (*service) getSystemVersion(w http.ResponseWriter, _ *http.Request) {
 func (*service) getSystemDebug(w http.ResponseWriter, _ *http.Request) {
 	names := l.Facilities()
 	enabled := l.FacilityDebugging()
-	sort.Strings(enabled)
+	slices.Sort(enabled)
 	sendJSON(w, map[string]interface{}{
 		"facilities": names,
 		"enabled":    enabled,
@@ -1535,8 +1536,8 @@ func (*service) getLang(w http.ResponseWriter, r *http.Request) {
 		langs = append(langs, code)
 	}
 	// Reorder by descending q value
-	sort.SliceStable(langs, func(i, j int) bool {
-		return weights[langs[i]] > weights[langs[j]]
+	slices.SortStableFunc(langs, func(i, j string) int {
+		return cmp.Compare(weights[j], weights[i])
 	})
 	sendJSON(w, langs)
 }
@@ -1822,8 +1823,8 @@ func browseFiles(ffs fs.Filesystem, search string) []string {
 	}
 
 	// sort to return matches in deterministic order (don't depend on file system order)
-	sort.Strings(exactMatches)
-	sort.Strings(caseInsMatches)
+	slices.Sort(exactMatches)
+	slices.Sort(caseInsMatches)
 	return append(exactMatches, caseInsMatches...)
 }
 
@@ -1920,7 +1921,7 @@ func dirNames(dir string) []string {
 		}
 	}
 
-	sort.Strings(dirs)
+	slices.Sort(dirs)
 	return dirs
 }
 

+ 2 - 2
lib/build/build.go

@@ -12,7 +12,7 @@ import (
 	"os"
 	"regexp"
 	"runtime"
-	"sort"
+	"slices"
 	"strconv"
 	"strings"
 	"time"
@@ -109,7 +109,7 @@ func TagsList() []string {
 		tags = append(tags, Extra)
 	}
 
-	sort.Strings(tags)
+	slices.Sort(tags)
 	return tags
 }
 

+ 3 - 2
lib/config/config.go

@@ -17,6 +17,7 @@ import (
 	"net/url"
 	"os"
 	"reflect"
+	"slices"
 	"sort"
 	"strconv"
 	"strings"
@@ -380,8 +381,8 @@ func (cfg *Configuration) prepareFolders(myID protocol.DeviceID, existingDevices
 		}
 	}
 	// Ensure that the folder list is sorted by ID
-	sort.Slice(cfg.Folders, func(a, b int) bool {
-		return cfg.Folders[a].ID < cfg.Folders[b].ID
+	slices.SortFunc(cfg.Folders, func(a, b FolderConfiguration) int {
+		return strings.Compare(a.ID, b.ID)
 	})
 	return sharedFolders, nil
 }

+ 2 - 2
lib/config/config_test.go

@@ -17,7 +17,7 @@ import (
 	"path/filepath"
 	"reflect"
 	"runtime"
-	"sort"
+	"slices"
 	"strings"
 	"testing"
 
@@ -911,7 +911,7 @@ func TestV14ListenAddressesMigration(t *testing.T) {
 			t.Error("Configuration was not converted")
 		}
 
-		sort.Strings(tc[2])
+		slices.Sort(tc[2])
 		if !reflect.DeepEqual(cfg.Options.RawListenAddresses, tc[2]) {
 			t.Errorf("Migration error; actual %#v != expected %#v", cfg.Options.RawListenAddresses, tc[2])
 		}

+ 5 - 4
lib/config/migrations.go

@@ -7,11 +7,12 @@
 package config
 
 import (
+	"cmp"
 	"net/url"
 	"os"
 	"path"
 	"path/filepath"
-	"sort"
+	"slices"
 	"strings"
 	"sync"
 
@@ -65,8 +66,8 @@ type migrationSet []migration
 func (ms migrationSet) apply(cfg *Configuration) {
 	// Make sure we apply the migrations in target version order regardless
 	// of how it was defined.
-	sort.Slice(ms, func(a, b int) bool {
-		return ms[a].targetVersion < ms[b].targetVersion
+	slices.SortFunc(ms, func(a, b migration) int {
+		return cmp.Compare(a.targetVersion, b.targetVersion)
 	})
 
 	// Apply all migrations.
@@ -349,7 +350,7 @@ func migrateToConfigV14(cfg *Configuration) {
 	cfg.Options.DeprecatedRelayServers = nil
 
 	// For consistency
-	sort.Strings(cfg.Options.RawListenAddresses)
+	slices.Sort(cfg.Options.RawListenAddresses)
 
 	var newAddrs []string
 	for _, addr := range cfg.Options.RawGlobalAnnServers {

+ 4 - 3
lib/config/versioningconfiguration.go

@@ -9,7 +9,8 @@ package config
 import (
 	"encoding/json"
 	"encoding/xml"
-	"sort"
+	"slices"
+	"strings"
 
 	"github.com/syncthing/syncthing/lib/structutil"
 )
@@ -84,8 +85,8 @@ func (c *VersioningConfiguration) toInternal() internalVersioningConfiguration {
 	for k, v := range c.Params {
 		tmp.Params = append(tmp.Params, internalParam{k, v})
 	}
-	sort.Slice(tmp.Params, func(a, b int) bool {
-		return tmp.Params[a].Key < tmp.Params[b].Key
+	slices.SortFunc(tmp.Params, func(a, b internalParam) int {
+		return strings.Compare(a.Key, b.Key)
 	})
 	return tmp
 }

+ 1 - 2
lib/connections/service.go

@@ -23,7 +23,6 @@ import (
 	"net"
 	"net/url"
 	"slices"
-	"sort"
 	"strings"
 	stdsync "sync"
 	"time"
@@ -1151,7 +1150,7 @@ func (s *service) dialParallel(ctx context.Context, deviceID protocol.DeviceID,
 	}
 
 	// Sort the priorities so that we dial lowest first (which means highest...)
-	sort.Ints(priorities)
+	slices.Sort(priorities)
 
 	sema := semaphore.MultiSemaphore{semaphore.New(dialMaxParallelPerDevice), parentSema}
 	for _, prio := range priorities {

+ 2 - 2
lib/db/smallindex.go

@@ -8,7 +8,7 @@ package db
 
 import (
 	"encoding/binary"
-	"sort"
+	"slices"
 
 	"github.com/syncthing/syncthing/lib/db/backend"
 	"github.com/syncthing/syncthing/lib/sync"
@@ -147,6 +147,6 @@ func (i *smallIndex) Values() []string {
 	}
 	i.mut.Unlock()
 
-	sort.Strings(vals)
+	slices.Sort(vals)
 	return vals
 }

+ 2 - 2
lib/discover/manager.go

@@ -13,7 +13,7 @@ import (
 	"context"
 	"crypto/tls"
 	"fmt"
-	"sort"
+	"slices"
 	"time"
 
 	"github.com/thejerf/suture/v4"
@@ -159,7 +159,7 @@ func (m *manager) Lookup(ctx context.Context, deviceID protocol.DeviceID) (addre
 	m.mut.RUnlock()
 
 	addresses = stringutil.UniqueTrimmedStrings(addresses)
-	sort.Strings(addresses)
+	slices.Sort(addresses)
 
 	l.Debugln("lookup results for", deviceID)
 	l.Debugln("  addresses: ", addresses)

+ 6 - 7
lib/fs/basicfs_test.go

@@ -12,7 +12,7 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
-	"sort"
+	"slices"
 	"strconv"
 	"strings"
 	"syscall"
@@ -218,7 +218,7 @@ func TestDirNames(t *testing.T) {
 		"a",
 		"bC",
 	}
-	sort.Strings(testCases)
+	slices.Sort(testCases)
 
 	for _, sub := range testCases {
 		if err := os.Mkdir(filepath.Join(dir, sub), 0o777); err != nil {
@@ -229,7 +229,7 @@ func TestDirNames(t *testing.T) {
 	if dirs, err := fs.DirNames("."); err != nil || len(dirs) != len(testCases) {
 		t.Errorf("%s %s %s", err, dirs, testCases)
 	} else {
-		sort.Strings(dirs)
+		slices.Sort(dirs)
 		for i := range dirs {
 			if dirs[i] != testCases[i] {
 				t.Errorf("%s != %s", dirs[i], testCases[i])
@@ -321,8 +321,8 @@ func TestGlob(t *testing.T) {
 
 	for _, testCase := range testCases {
 		results, err := fs.Glob(testCase.pattern)
-		sort.Strings(results)
-		sort.Strings(testCase.matches)
+		slices.Sort(results)
+		slices.Sort(testCase.matches)
 		if err != nil {
 			t.Error(err)
 		}
@@ -628,8 +628,7 @@ func TestXattr(t *testing.T) {
 			Value: value,
 		})
 	}
-	sort.Slice(attrs, func(i, j int) bool { return attrs[i].Name < attrs[j].Name })
-
+	slices.SortFunc(attrs, func(a, b protocol.Xattr) int { return strings.Compare(a.Name, b.Name) })
 	// Set the xattrs, read them back and compare
 	if err := tfs.SetXattr("/test", attrs, testXattrFilter{}); err != nil {
 		t.Fatal(err)

+ 2 - 2
lib/fs/basicfs_xattr_bsdish.go

@@ -12,7 +12,7 @@ package fs
 import (
 	"errors"
 	"fmt"
-	"sort"
+	"slices"
 	"unsafe"
 
 	"golang.org/x/sys/unix"
@@ -69,7 +69,7 @@ func listXattr(path string) ([]string, error) {
 		}
 	}
 
-	sort.Strings(attrs)
+	slices.Sort(attrs)
 	return attrs, nil
 }
 

+ 2 - 2
lib/fs/basicfs_xattr_linuxish.go

@@ -12,7 +12,7 @@ package fs
 import (
 	"errors"
 	"fmt"
-	"sort"
+	"slices"
 	"strings"
 
 	"golang.org/x/sys/unix"
@@ -38,6 +38,6 @@ func listXattr(path string) ([]string, error) {
 	buf = buf[:size]
 	attrs := compact(strings.Split(string(buf), "\x00"))
 
-	sort.Strings(attrs)
+	slices.Sort(attrs)
 	return attrs, nil
 }

+ 2 - 2
lib/fs/casefs_test.go

@@ -11,7 +11,7 @@ import (
 	"fmt"
 	"path/filepath"
 	"runtime"
-	"sort"
+	"slices"
 	"strings"
 	"testing"
 	"time"
@@ -344,7 +344,7 @@ func fakefsForBenchmark(nfiles int, latency time.Duration) (Filesystem, []string
 		return nil, nil, errors.New("didn't find enough stuff")
 	}
 
-	sort.Strings(paths)
+	slices.Sort(paths)
 
 	return fsys, paths, nil
 }

+ 3 - 3
lib/fs/fakefs_test.go

@@ -14,7 +14,7 @@ import (
 	"path"
 	"path/filepath"
 	"runtime"
-	"sort"
+	"slices"
 	"testing"
 	"time"
 
@@ -369,8 +369,8 @@ func assertDir(t *testing.T, fs Filesystem, directory string, filenames []string
 	if path.Clean(directory) == "/" {
 		filenames = append(filenames, ".stfolder")
 	}
-	sort.Strings(filenames)
-	sort.Strings(got)
+	slices.Sort(filenames)
+	slices.Sort(got)
 
 	if len(filenames) != len(got) {
 		t.Errorf("want %s, got %s", filenames, got)

+ 2 - 1
lib/model/folder.go

@@ -12,6 +12,7 @@ import (
 	"fmt"
 	"math/rand"
 	"path/filepath"
+	"slices"
 	"sort"
 	"time"
 
@@ -1341,7 +1342,7 @@ func unifySubs(dirs []string, exists func(dir string) bool) []string {
 	if len(dirs) == 0 {
 		return nil
 	}
-	sort.Strings(dirs)
+	slices.Sort(dirs)
 	if dirs[0] == "" || dirs[0] == "." || dirs[0] == string(fs.PathSeparator) {
 		return nil
 	}

+ 2 - 3
lib/model/model_test.go

@@ -18,7 +18,6 @@ import (
 	"path/filepath"
 	"runtime/pprof"
 	"slices"
-	"sort"
 	"strconv"
 	"strings"
 	"sync"
@@ -4092,8 +4091,8 @@ func equalStringsInAnyOrder(a, b []string) bool {
 	if len(a) != len(b) {
 		return false
 	}
-	sort.Strings(a)
-	sort.Strings(b)
+	slices.Sort(a)
+	slices.Sort(b)
 	for i := range a {
 		if a[i] != b[i] {
 			return false

+ 2 - 2
lib/relay/client/dynamic.go

@@ -10,7 +10,7 @@ import (
 	"fmt"
 	"net/http"
 	"net/url"
-	"sort"
+	"slices"
 	"sync"
 	"time"
 
@@ -166,7 +166,7 @@ func relayAddressesOrder(ctx context.Context, input []string) []string {
 		ids = append(ids, id)
 	}
 
-	sort.Ints(ids)
+	slices.Sort(ids)
 
 	addresses := make([]string, 0, len(input))
 	for _, id := range ids {

+ 3 - 3
lib/syncthing/syncthing.go

@@ -15,7 +15,7 @@ import (
 	"net/http"
 	"os"
 	"runtime"
-	"sort"
+	"slices"
 	"strings"
 	"sync"
 	"time"
@@ -437,8 +437,8 @@ func printServiceTree(w io.Writer, sup supervisor, level int) {
 	printService(w, sup, level)
 
 	svcs := sup.Services()
-	sort.Slice(svcs, func(a, b int) bool {
-		return fmt.Sprint(svcs[a]) < fmt.Sprint(svcs[b])
+	slices.SortFunc(svcs, func(a, b suture.Service) int {
+		return strings.Compare(fmt.Sprint(a), fmt.Sprint(b))
 	})
 
 	for _, svc := range svcs {

+ 3 - 3
lib/ur/usage_report.go

@@ -16,7 +16,7 @@ import (
 	"net/http"
 	"os"
 	"runtime"
-	"sort"
+	"slices"
 	"strings"
 	"sync"
 	"time"
@@ -162,7 +162,7 @@ func (s *Service) reportData(ctx context.Context, urVersion int, preview bool) (
 			l.Warnf("Unhandled versioning type for usage reports: %s", cfg.Versioning.Type)
 		}
 	}
-	sort.Ints(report.RescanIntvs)
+	slices.Sort(report.RescanIntvs)
 
 	for _, cfg := range s.cfg.Devices() {
 		if cfg.Introducer {
@@ -295,7 +295,7 @@ func (s *Service) reportData(ctx context.Context, urVersion int, preview bool) (
 				report.FolderUsesV3.SyncOwnership++
 			}
 		}
-		sort.Ints(report.FolderUsesV3.FsWatcherDelays)
+		slices.Sort(report.FolderUsesV3.FsWatcherDelays)
 
 		for _, cfg := range s.cfg.Devices() {
 			if cfg.Untrusted {

+ 2 - 2
lib/versioner/simple.go

@@ -8,7 +8,7 @@ package versioner
 
 import (
 	"context"
-	"sort"
+	"slices"
 	"strconv"
 	"time"
 
@@ -79,7 +79,7 @@ func (v simple) toRemove(versions []string, now time.Time) []string {
 	var remove []string
 
 	// The list of versions may or may not be properly sorted.
-	sort.Strings(versions)
+	slices.Sort(versions)
 
 	// If the amount of elements exceeds the limit: the oldest elements are to be removed.
 	if len(versions) > v.keep {

+ 2 - 2
lib/versioner/staggered.go

@@ -9,7 +9,7 @@ package versioner
 import (
 	"context"
 	"fmt"
-	"sort"
+	"slices"
 	"strconv"
 	"time"
 
@@ -69,7 +69,7 @@ func (v *staggered) toRemove(versions []string, now time.Time) []string {
 	var remove []string
 
 	// The list of versions may or may not be properly sorted.
-	sort.Strings(versions)
+	slices.Sort(versions)
 
 	for _, version := range versions {
 		versionTime, err := time.ParseInLocation(TimeFormat, extractTag(version), time.Local)

+ 3 - 3
lib/versioner/staggered_test.go

@@ -9,7 +9,7 @@ package versioner
 import (
 	"os"
 	"path/filepath"
-	"sort"
+	"slices"
 	"strconv"
 	"testing"
 	"time"
@@ -97,7 +97,7 @@ func TestStaggeredVersioningVersionCount(t *testing.T) {
 		"test~20150416-135958", // 365 days 2 seconds ago
 		"test~20150414-140000", // 367 days ago
 	}
-	sort.Strings(delete)
+	slices.Sort(delete)
 
 	cfg := config.FolderConfiguration{
 		FilesystemType: config.FilesystemTypeBasic,
@@ -111,7 +111,7 @@ func TestStaggeredVersioningVersionCount(t *testing.T) {
 
 	v := newStaggered(cfg).(*staggered)
 	rem := v.toRemove(versionsWithMtime, now)
-	sort.Strings(rem)
+	slices.Sort(rem)
 
 	if diff, equal := messagediff.PrettyDiff(delete, rem); !equal {
 		t.Errorf("Incorrect deleted files; got %v, expected %v\n%v", rem, delete, diff)

+ 2 - 2
lib/versioner/util.go

@@ -13,7 +13,7 @@ import (
 	"os"
 	"path/filepath"
 	"regexp"
-	"sort"
+	"slices"
 	"strings"
 	"time"
 
@@ -339,7 +339,7 @@ func findAllVersions(fs fs.Filesystem, filePath string) []string {
 		return nil
 	}
 	versions = stringutil.UniqueTrimmedStrings(versions)
-	sort.Strings(versions)
+	slices.Sort(versions)
 
 	return versions
 }

+ 2 - 2
script/transifexdl.go

@@ -17,7 +17,7 @@ import (
 	"net/http"
 	"os"
 	"regexp"
-	"sort"
+	"slices"
 	"strings"
 )
 
@@ -93,7 +93,7 @@ func main() {
 }
 
 func saveValidLangs(langs []string) {
-	sort.Strings(langs)
+	slices.Sort(langs)
 	fd, err := os.Create("valid-langs.js")
 	if err != nil {
 		log.Fatal(err)

+ 2 - 2
script/weblatedl.go

@@ -17,7 +17,7 @@ import (
 	"net/http"
 	"os"
 	"regexp"
-	"sort"
+	"slices"
 	"strings"
 )
 
@@ -116,7 +116,7 @@ func reformatLanguageCode(origCode string) string {
 }
 
 func saveValidLangs(langs []string) {
-	sort.Strings(langs)
+	slices.Sort(langs)
 	fd, err := os.Create("valid-langs.js")
 	if err != nil {
 		log.Fatal(err)