From 995e7fd8937107892755dd0a6abf86eb825e1dac Mon Sep 17 00:00:00 2001 From: Julio Lopez <1953782+julio-lopez@users.noreply.github.com> Date: Thu, 23 Oct 2025 17:11:38 -0700 Subject: [PATCH] refactor(general): modernize (#4903) Applies the modernize changes for the following categories: - mapsloop - stringsseq - stringscutprefix - sortslice --- cli/command_acl_add.go | 2 +- cli/command_benchmark_compression.go | 2 +- cli/command_blob_shards_modify.go | 4 ++-- cli/command_policy_set_scheduling.go | 6 +++--- cli/command_server_tls.go | 4 ++-- fs/cachefs/cache_test.go | 5 ++--- internal/blobtesting/asserts.go | 6 ++---- internal/blobtesting/map.go | 6 ++---- internal/blobtesting/object_locking_map.go | 6 ++---- internal/cache/content_cache_test.go | 5 +---- internal/releasable/releaseable_tracker.go | 5 ++--- internal/server/server.go | 9 +++------ internal/server/server_mount_manager.go | 5 ++--- internal/testutil/serverparameters.go | 16 ++++++++-------- internal/testutil/tmpdir.go | 2 +- internal/uitask/uitask_counter.go | 6 +++--- notification/sender/webhook/webhook_sender.go | 2 +- repo/blob/webdav/webdav_storage_test.go | 5 ++--- repo/compression/compressor_test.go | 6 ++---- repo/manifest/manifest_manager_test.go | 6 ++---- snapshot/manager.go | 5 ++--- tests/end_to_end_test/auto_update_test.go | 5 ++--- .../end_to_end_test/repository_connect_test.go | 4 ++-- tests/end_to_end_test/snapshot_fail_test.go | 9 +++------ .../robustness/fiofilewriter/fio_filewriter.go | 17 +++++------------ tests/tools/fio/options.go | 9 +++------ tests/tools/kopiarunner/kopia_snapshotter.go | 12 ++++++------ tools/gettool/gettool.go | 2 +- 28 files changed, 68 insertions(+), 103 deletions(-) diff --git a/cli/command_acl_add.go b/cli/command_acl_add.go index df34ed7b4..6c05dc5d2 100644 --- a/cli/command_acl_add.go +++ b/cli/command_acl_add.go @@ -29,7 +29,7 @@ func (c *commandACLAdd) setup(svc appServices, parent commandParent) { func (c *commandACLAdd) run(ctx context.Context, rep repo.RepositoryWriter) error { r := acl.TargetRule{} - for _, v := range strings.Split(c.target, ",") { + for v := range strings.SplitSeq(c.target, ",") { parts := strings.SplitN(v, "=", 2) //nolint:mnd if len(parts) != 2 { //nolint:mnd return errors.Errorf("invalid target labels %q, must be key=value", v) diff --git a/cli/command_benchmark_compression.go b/cli/command_benchmark_compression.go index ff37c1462..93a72333d 100644 --- a/cli/command_benchmark_compression.go +++ b/cli/command_benchmark_compression.go @@ -97,7 +97,7 @@ func (c *commandBenchmarkCompression) shouldIncludeAlgorithm(name compression.Na return true } - for _, a := range strings.Split(c.algorithms, ",") { + for a := range strings.SplitSeq(c.algorithms, ",") { if strings.HasPrefix(string(name), a) { return true } diff --git a/cli/command_blob_shards_modify.go b/cli/command_blob_shards_modify.go index 970c58b9a..5012c71f6 100644 --- a/cli/command_blob_shards_modify.go +++ b/cli/command_blob_shards_modify.go @@ -64,9 +64,9 @@ func parseShardSpec(shards string) ([]int, error) { return result, nil } - parts := strings.Split(shards, ",") + parts := strings.SplitSeq(shards, ",") - for _, p := range parts { + for p := range parts { if p == "" { continue } diff --git a/cli/command_policy_set_scheduling.go b/cli/command_policy_set_scheduling.go index e63e26d47..03af70ba9 100644 --- a/cli/command_policy_set_scheduling.go +++ b/cli/command_policy_set_scheduling.go @@ -50,7 +50,7 @@ func (c *policySchedulingFlags) setScheduleFromFlags(ctx context.Context, sp *po var timesOfDay []policy.TimeOfDay for _, tods := range c.policySetTimesOfDay { - for _, tod := range strings.Split(tods, ",") { + for tod := range strings.SplitSeq(tods, ",") { if tod == inheritPolicyString { timesOfDay = nil break @@ -127,8 +127,8 @@ func splitCronExpressions(expr string) []string { var result []string - parts := strings.Split(expr, ";") - for _, part := range parts { + parts := strings.SplitSeq(expr, ";") + for part := range parts { part = strings.TrimSpace(part) if part == "" { continue diff --git a/cli/command_server_tls.go b/cli/command_server_tls.go index ab7fb078f..6c4be5a26 100644 --- a/cli/command_server_tls.go +++ b/cli/command_server_tls.go @@ -47,8 +47,8 @@ func (c *commandServerStart) startServerWithOptionalTLS(ctx context.Context, htt switch len(listeners) { case 0: - if strings.HasPrefix(httpServer.Addr, "unix:") { - l, err = net.Listen("unix", strings.TrimPrefix(httpServer.Addr, "unix:")) + if after, ok := strings.CutPrefix(httpServer.Addr, "unix:"); ok { + l, err = net.Listen("unix", after) } else { l, err = net.Listen("tcp", httpServer.Addr) } diff --git a/fs/cachefs/cache_test.go b/fs/cachefs/cache_test.go index cad706fe6..6f1229f6d 100644 --- a/fs/cachefs/cache_test.go +++ b/fs/cachefs/cache_test.go @@ -3,6 +3,7 @@ import ( "context" "fmt" + "maps" "path/filepath" "reflect" "runtime" @@ -135,9 +136,7 @@ func errorPrefix() string { func (cv *cacheVerifier) reset() { cv.lastCallCounter = make(map[string]int) - for k, v := range cv.cacheSource.callCounter { - cv.lastCallCounter[k] = v - } + maps.Copy(cv.lastCallCounter, cv.cacheSource.callCounter) } type lockState struct { diff --git a/internal/blobtesting/asserts.go b/internal/blobtesting/asserts.go index 45fe473b0..09c88d2b3 100644 --- a/internal/blobtesting/asserts.go +++ b/internal/blobtesting/asserts.go @@ -4,7 +4,7 @@ "bytes" "context" "reflect" - "sort" + "slices" "testing" "time" @@ -199,9 +199,7 @@ func AssertListResultsIDs(ctx context.Context, t *testing.T, s blob.Storage, pre func sorted(s []blob.ID) []blob.ID { x := append([]blob.ID(nil), s...) - sort.Slice(x, func(i, j int) bool { - return x[i] < x[j] - }) + slices.Sort(x) return x } diff --git a/internal/blobtesting/map.go b/internal/blobtesting/map.go index db06376bd..cead45069 100644 --- a/internal/blobtesting/map.go +++ b/internal/blobtesting/map.go @@ -3,7 +3,7 @@ import ( "bytes" "context" - "sort" + "slices" "strings" "sync" "time" @@ -181,9 +181,7 @@ func (s *mapStorage) ListBlobs(ctx context.Context, prefix blob.ID, callback fun s.mutex.RUnlock() - sort.Slice(keys, func(i, j int) bool { - return keys[i] < keys[j] - }) + slices.Sort(keys) for _, k := range keys { s.mutex.RLock() diff --git a/internal/blobtesting/object_locking_map.go b/internal/blobtesting/object_locking_map.go index 6fbb20c34..4ac825349 100644 --- a/internal/blobtesting/object_locking_map.go +++ b/internal/blobtesting/object_locking_map.go @@ -3,7 +3,7 @@ import ( "bytes" "context" - "sort" + "slices" "strings" "sync" "time" @@ -237,9 +237,7 @@ func (s *objectLockingMap) ListBlobs(ctx context.Context, prefix blob.ID, callba s.mutex.RUnlock() - sort.Slice(keys, func(i, j int) bool { - return keys[i] < keys[j] - }) + slices.Sort(keys) for _, k := range keys { m, err := s.GetMetadata(ctx, k) diff --git a/internal/cache/content_cache_test.go b/internal/cache/content_cache_test.go index 0bc445983..f47ff2b93 100644 --- a/internal/cache/content_cache_test.go +++ b/internal/cache/content_cache_test.go @@ -4,7 +4,6 @@ "bytes" "context" "slices" - "sort" "sync" "testing" "time" @@ -345,9 +344,7 @@ func verifyStorageContentList(t *testing.T, st cache.Storage, expectedContents . return nil })) - sort.Slice(foundContents, func(i, j int) bool { - return foundContents[i] < foundContents[j] - }) + slices.Sort(foundContents) assert.Equal(t, expectedContents, foundContents, "unexpected content list") } diff --git a/internal/releasable/releaseable_tracker.go b/internal/releasable/releaseable_tracker.go index efeeb70dd..c0109c02d 100644 --- a/internal/releasable/releaseable_tracker.go +++ b/internal/releasable/releaseable_tracker.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" + "maps" "runtime/debug" "sync" @@ -92,9 +93,7 @@ func (s *perKindTracker) active() map[any]string { defer s.mu.Unlock() res := map[any]string{} - for k, v := range s.items { - res[k] = v - } + maps.Copy(res, s.items) return res } diff --git a/internal/server/server.go b/internal/server/server.go index e02c10a54..7e39d7b3e 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -8,6 +8,7 @@ "fmt" "html" "io" + "maps" "net/http" "net/url" "strings" @@ -708,9 +709,7 @@ func (s *Server) syncSourcesLocked(ctx context.Context) error { // copy existing sources to a map, from which we will remove sources that are found // in the repository oldSourceManagers := map[snapshot.SourceInfo]*sourceManager{} - for k, v := range s.sourceManagers { - oldSourceManagers[k] = v - } + maps.Copy(oldSourceManagers, s.sourceManagers) for src := range sources { if sm, ok := oldSourceManagers[src]; ok { @@ -1048,9 +1047,7 @@ func (s *Server) snapshotAllSourceManagers() map[snapshot.SourceInfo]*sourceMana result := map[snapshot.SourceInfo]*sourceManager{} - for k, v := range s.sourceManagers { - result[k] = v - } + maps.Copy(result, s.sourceManagers) return result } diff --git a/internal/server/server_mount_manager.go b/internal/server/server_mount_manager.go index fab60d36a..de17ea7d0 100644 --- a/internal/server/server_mount_manager.go +++ b/internal/server/server_mount_manager.go @@ -2,6 +2,7 @@ import ( "context" + "maps" "github.com/pkg/errors" @@ -42,9 +43,7 @@ func (s *Server) listMounts() map[object.ID]mount.Controller { result := map[object.ID]mount.Controller{} - for oid, c := range s.mounts { - result[oid] = c - } + maps.Copy(result, s.mounts) return result } diff --git a/internal/testutil/serverparameters.go b/internal/testutil/serverparameters.go index 75a1d577a..66cc2ff01 100644 --- a/internal/testutil/serverparameters.go +++ b/internal/testutil/serverparameters.go @@ -21,21 +21,21 @@ type ServerParameters struct { // ProcessOutput processes output lines from a server that's starting up. func (s *ServerParameters) ProcessOutput(l string) bool { - if strings.HasPrefix(l, serverOutputAddress) { - s.BaseURL = strings.TrimPrefix(l, serverOutputAddress) + if after, ok := strings.CutPrefix(l, serverOutputAddress); ok { + s.BaseURL = after return false } - if strings.HasPrefix(l, serverOutputCertSHA256) { - s.SHA256Fingerprint = strings.TrimPrefix(l, serverOutputCertSHA256) + if after, ok := strings.CutPrefix(l, serverOutputCertSHA256); ok { + s.SHA256Fingerprint = after } - if strings.HasPrefix(l, serverOutputPassword) { - s.Password = strings.TrimPrefix(l, serverOutputPassword) + if after, ok := strings.CutPrefix(l, serverOutputPassword); ok { + s.Password = after } - if strings.HasPrefix(l, serverOutputControlPassword) { - s.ServerControlPassword = strings.TrimPrefix(l, serverOutputControlPassword) + if after, ok := strings.CutPrefix(l, serverOutputControlPassword); ok { + s.ServerControlPassword = after } return true diff --git a/internal/testutil/tmpdir.go b/internal/testutil/tmpdir.go index ca7fb5d7b..e2080ba43 100644 --- a/internal/testutil/tmpdir.go +++ b/internal/testutil/tmpdir.go @@ -176,7 +176,7 @@ func splitLines(s string) []string { } var result []string - for _, l := range strings.Split(s, "\n") { + for l := range strings.SplitSeq(s, "\n") { result = append(result, strings.TrimRight(l, "\r")) } diff --git a/internal/uitask/uitask_counter.go b/internal/uitask/uitask_counter.go index 25eb13dbd..54afedf19 100644 --- a/internal/uitask/uitask_counter.go +++ b/internal/uitask/uitask_counter.go @@ -1,5 +1,7 @@ package uitask +import "maps" + // CounterValue describes the counter value reported by task with optional units for presentation. type CounterValue struct { Value int64 `json:"value"` @@ -49,9 +51,7 @@ func ErrorCounter(v int64) CounterValue { func cloneCounters(c map[string]CounterValue) map[string]CounterValue { newCounters := map[string]CounterValue{} - for k, v := range c { - newCounters[k] = v - } + maps.Copy(newCounters, c) return newCounters } diff --git a/notification/sender/webhook/webhook_sender.go b/notification/sender/webhook/webhook_sender.go index 1e860de91..6e996ebcb 100644 --- a/notification/sender/webhook/webhook_sender.go +++ b/notification/sender/webhook/webhook_sender.go @@ -34,7 +34,7 @@ func (p *webhookProvider) Send(ctx context.Context, msg *sender.Message) error { req.Header.Set("Subject", msg.Subject) // add extra headers from options - for _, l := range strings.Split(p.opt.Headers, "\n") { + for l := range strings.SplitSeq(p.opt.Headers, "\n") { const numParts = 2 if parts := strings.SplitN(strings.TrimSpace(l), ":", numParts); len(parts) == numParts { req.Header.Set(parts[0], strings.TrimSpace(parts[1])) diff --git a/repo/blob/webdav/webdav_storage_test.go b/repo/blob/webdav/webdav_storage_test.go index e9ec4e816..fa5814656 100644 --- a/repo/blob/webdav/webdav_storage_test.go +++ b/repo/blob/webdav/webdav_storage_test.go @@ -5,6 +5,7 @@ "context" "fmt" "io" + "maps" "net/http" "net/http/httptest" "os" @@ -136,9 +137,7 @@ func transformMissingPUTs(next http.Handler) http.HandlerFunc { w.WriteHeader(http.StatusForbidden) } else { // Passthrough recorded response headers, status code, and body - for header, values := range rec.Header() { - w.Header()[header] = values - } + maps.Copy(w.Header(), rec.Header()) w.WriteHeader(result.StatusCode) io.Copy(w, result.Body) diff --git a/repo/compression/compressor_test.go b/repo/compression/compressor_test.go index 60c4f4200..73cf0b54d 100644 --- a/repo/compression/compressor_test.go +++ b/repo/compression/compressor_test.go @@ -4,7 +4,7 @@ "bytes" "crypto/rand" "fmt" - "sort" + "slices" "testing" "github.com/kopia/kopia/internal/testutil" @@ -98,9 +98,7 @@ func BenchmarkCompressor(b *testing.B) { sortedNames = append(sortedNames, id) } - sort.Slice(sortedNames, func(i, j int) bool { - return sortedNames[i] < sortedNames[j] - }) + slices.Sort(sortedNames) for _, id := range sortedNames { comp := ByName[id] diff --git a/repo/manifest/manifest_manager_test.go b/repo/manifest/manifest_manager_test.go index 4bd55f638..880cb20e7 100644 --- a/repo/manifest/manifest_manager_test.go +++ b/repo/manifest/manifest_manager_test.go @@ -5,7 +5,7 @@ "encoding/json" "fmt" "reflect" - "sort" + "slices" "strings" "testing" "time" @@ -302,9 +302,7 @@ func verifyMatches(ctx context.Context, t *testing.T, mgr *Manager, labels map[s } func sortIDs(s []ID) { - sort.Slice(s, func(i, j int) bool { - return s[i] < s[j] - }) + slices.Sort(s) } type contentManagerOpts struct { diff --git a/snapshot/manager.go b/snapshot/manager.go index a35828d28..99408d4a0 100644 --- a/snapshot/manager.go +++ b/snapshot/manager.go @@ -3,6 +3,7 @@ import ( "context" + "maps" "github.com/pkg/errors" @@ -195,9 +196,7 @@ func ListSnapshotManifests(ctx context.Context, rep repo.Repository, src *Source labels = sourceInfoToLabels(*src) } - for key, value := range tags { - labels[key] = value - } + maps.Copy(labels, tags) entries, err := rep.FindManifests(ctx, labels) if err != nil { diff --git a/tests/end_to_end_test/auto_update_test.go b/tests/end_to_end_test/auto_update_test.go index 481eb1655..0f38f8303 100644 --- a/tests/end_to_end_test/auto_update_test.go +++ b/tests/end_to_end_test/auto_update_test.go @@ -2,6 +2,7 @@ import ( "encoding/json" + "maps" "os" "path/filepath" "testing" @@ -46,9 +47,7 @@ func TestAutoUpdateEnableTest(t *testing.T) { "repo", "create", "filesystem", "--path", e.RepoDir, }, tc.extraArgs...) - for k, v := range tc.extraEnv { - e.Environment[k] = v - } + maps.Copy(e.Environment, tc.extraEnv) e.RunAndExpectSuccess(t, args...) diff --git a/tests/end_to_end_test/repository_connect_test.go b/tests/end_to_end_test/repository_connect_test.go index fd54fff93..029434797 100644 --- a/tests/end_to_end_test/repository_connect_test.go +++ b/tests/end_to_end_test/repository_connect_test.go @@ -93,8 +93,8 @@ func TestReconnectUsingToken(t *testing.T) { // look for output line containing the prefix - this will be our reconnect command for _, l := range lines { - if strings.HasPrefix(l, prefix) { - reconnectArgs = strings.Split(strings.TrimPrefix(l, prefix), " ") + if after, ok := strings.CutPrefix(l, prefix); ok { + reconnectArgs = strings.Split(after, " ") } } diff --git a/tests/end_to_end_test/snapshot_fail_test.go b/tests/end_to_end_test/snapshot_fail_test.go index 3e40ce0cc..79bb58695 100644 --- a/tests/end_to_end_test/snapshot_fail_test.go +++ b/tests/end_to_end_test/snapshot_fail_test.go @@ -2,6 +2,7 @@ import ( "fmt" + "maps" "math/rand" "os" "path/filepath" @@ -351,13 +352,9 @@ func() { oldEnv := e.Environment e.Environment = map[string]string{} - for k, v := range oldEnv { - e.Environment[k] = v - } + maps.Copy(e.Environment, oldEnv) - for k, v := range snapshotCreateEnv { - e.Environment[k] = v - } + maps.Copy(e.Environment, snapshotCreateEnv) defer func() { e.Environment = oldEnv }() diff --git a/tests/robustness/fiofilewriter/fio_filewriter.go b/tests/robustness/fiofilewriter/fio_filewriter.go index b57122a6a..79e149e73 100644 --- a/tests/robustness/fiofilewriter/fio_filewriter.go +++ b/tests/robustness/fiofilewriter/fio_filewriter.go @@ -8,6 +8,7 @@ "context" "errors" "log" + "maps" "math/rand" "strconv" "syscall" @@ -147,13 +148,9 @@ func (fw *FileWriter) WriteRandomFiles(ctx context.Context, opts map[string]stri log.Printf("Writing files at depth %v (fileSize: %v-%v, numFiles: %v, blockSize: %v, dedupPcnt: %v, ioLimit: %v)\n", dirDepth, minFileSizeB, maxFileSizeB, numFiles, blockSize, dedupPcnt, ioLimit) retOpts := make(map[string]string, len(opts)) - for k, v := range opts { - retOpts[k] = v - } + maps.Copy(retOpts, opts) - for k, v := range fioOpts { - retOpts[k] = v - } + maps.Copy(retOpts, fioOpts) retOpts["dirDepth"] = strconv.Itoa(dirDepth) retOpts["relBasePath"] = relBasePath @@ -180,9 +177,7 @@ func (fw *FileWriter) DeleteRandomSubdirectory(ctx context.Context, opts map[str log.Printf("Deleting directory at depth %v\n", dirDepth) retOpts := make(map[string]string, len(opts)) - for k, v := range opts { - retOpts[k] = v - } + maps.Copy(retOpts, opts) retOpts["dirDepth"] = strconv.Itoa(dirDepth) @@ -213,9 +208,7 @@ func (fw *FileWriter) DeleteDirectoryContents(ctx context.Context, opts map[stri log.Printf("Deleting %d%% of directory contents at depth %v\n", pcnt, dirDepth) retOpts := make(map[string]string, len(opts)) - for k, v := range opts { - retOpts[k] = v - } + maps.Copy(retOpts, opts) retOpts["dirDepth"] = strconv.Itoa(dirDepth) retOpts["percent"] = strconv.Itoa(pcnt) diff --git a/tests/tools/fio/options.go b/tests/tools/fio/options.go index 7e987c2e0..390526904 100644 --- a/tests/tools/fio/options.go +++ b/tests/tools/fio/options.go @@ -2,6 +2,7 @@ import ( "fmt" + "maps" "path/filepath" "strconv" ) @@ -35,13 +36,9 @@ func (o Options) Merge(other Options) Options { out := make(map[string]string, len(o)+len(other)) - for k, v := range o { - out[k] = v - } + maps.Copy(out, o) - for k, v := range other { - out[k] = v - } + maps.Copy(out, other) return out } diff --git a/tests/tools/kopiarunner/kopia_snapshotter.go b/tests/tools/kopiarunner/kopia_snapshotter.go index 6ec3de2a9..2294556b3 100644 --- a/tests/tools/kopiarunner/kopia_snapshotter.go +++ b/tests/tools/kopiarunner/kopia_snapshotter.go @@ -317,11 +317,11 @@ func parseSnapID(lines []string) (string, error) { func parseSnapshotListForSnapshotIDs(output string) []string { var ret []string - lines := strings.Split(output, "\n") - for _, l := range lines { - fields := strings.Fields(l) + lines := strings.SplitSeq(output, "\n") + for l := range lines { + fields := strings.FieldsSeq(l) - for _, f := range fields { + for f := range fields { spl := strings.Split(f, "manifest:") if len(spl) == 2 { //nolint:mnd ret = append(ret, spl[1]) @@ -335,8 +335,8 @@ func parseSnapshotListForSnapshotIDs(output string) []string { func parseManifestListForSnapshotIDs(output string) []string { var ret []string - lines := strings.Split(output, "\n") - for _, l := range lines { + lines := strings.SplitSeq(output, "\n") + for l := range lines { fields := strings.Fields(l) typeFieldIdx := 5 diff --git a/tools/gettool/gettool.go b/tools/gettool/gettool.go index 8e7f7635e..545f49e3c 100644 --- a/tools/gettool/gettool.go +++ b/tools/gettool/gettool.go @@ -184,7 +184,7 @@ func main() { var errorCount int - for _, toolNameVersion := range strings.Split(*tool, ",") { + for toolNameVersion := range strings.SplitSeq(*tool, ",") { parts := strings.Split(toolNameVersion, ":") //nolint:mnd