diff --git a/deploy/upcloud/provision.go b/deploy/upcloud/provision.go index bc327f5..381b0f5 100644 --- a/deploy/upcloud/provision.go +++ b/deploy/upcloud/provision.go @@ -1522,7 +1522,7 @@ func writeRemoteCloudInit(ip, script string) error { // for cloud-init to complete before returning. func waitForSetup(ip, name string) error { fmt.Printf(" %s (%s): waiting for SSH...\n", name, ip) - for i := 0; i < 30; i++ { + for i := range 30 { _, err := runSSH(ip, "echo ssh_ready", false) if err == nil { break diff --git a/deploy/upcloud/status.go b/deploy/upcloud/status.go index 84a51f1..7d5abc8 100644 --- a/deploy/upcloud/status.go +++ b/deploy/upcloud/status.go @@ -76,13 +76,13 @@ func cmdStatus(token string) error { if err != nil { fmt.Printf(" Service: unreachable\n") } else { - lines := strings.Split(strings.TrimSpace(output), "\n") - for _, line := range lines { + lines := strings.SplitSeq(strings.TrimSpace(output), "\n") + for line := range lines { line = strings.TrimSpace(line) if line == "active" || line == "inactive" { fmt.Printf(" Service: %s\n", line) - } else if strings.HasPrefix(line, "health:") { - fmt.Printf(" Health: %s\n", strings.TrimPrefix(line, "health:")) + } else if after, ok := strings.CutPrefix(line, "health:"); ok { + fmt.Printf(" Health: %s\n", after) } } } @@ -101,13 +101,13 @@ func cmdStatus(token string) error { if err != nil { fmt.Printf(" Service: unreachable\n") } else { - lines := strings.Split(strings.TrimSpace(output), "\n") - for _, line := range lines { + lines := strings.SplitSeq(strings.TrimSpace(output), "\n") + for line := range lines { line = strings.TrimSpace(line) if line == "active" || line == "inactive" { fmt.Printf(" Service: %s\n", line) - } else if strings.HasPrefix(line, "health:") { - fmt.Printf(" Health: %s\n", strings.TrimPrefix(line, "health:")) + } else if after, ok := strings.CutPrefix(line, "health:"); ok { + fmt.Printf(" Health: %s\n", after) } } } diff --git a/pkg/appview/db/device_store_scan_test.go b/pkg/appview/db/device_store_scan_test.go index cba420d..b9184a0 100644 --- a/pkg/appview/db/device_store_scan_test.go +++ b/pkg/appview/db/device_store_scan_test.go @@ -31,7 +31,7 @@ func seedIndexedDeviceRows(t *testing.T, store *DeviceStore, did, handle string, t.Fatalf("GenerateFromPassword: %v", err) } - for i := 0; i < n; i++ { + for i := range n { hash := append([]byte(nil), base...) // Vary the tail so secret_hash stays UNIQUE, keeping the base64 alphabet. hash[len(hash)-1] = byte('a' + (i % 26)) diff --git a/pkg/appview/db/device_store_test.go b/pkg/appview/db/device_store_test.go index 598d270..913ef2e 100644 --- a/pkg/appview/db/device_store_test.go +++ b/pkg/appview/db/device_store_test.go @@ -723,7 +723,7 @@ func TestDeviceStore_LegacyDeviceBackfills(t *testing.T) { func TestDeviceStore_ValidateDoesNotScanIndexedRows(t *testing.T) { store := setupTestDB(t) createTestUser(t, store, "did:plc:alice123", "alice.bsky.social") - for i := 0; i < 5; i++ { + for i := range 5 { newDeviceForTest(t, store, "did:plc:alice123", "alice.bsky.social", fmt.Sprintf("Device %d", i)) } diff --git a/pkg/appview/holdpurge/queue_test.go b/pkg/appview/holdpurge/queue_test.go index 6af899c..cf70333 100644 --- a/pkg/appview/holdpurge/queue_test.go +++ b/pkg/appview/holdpurge/queue_test.go @@ -282,7 +282,7 @@ func TestSubmitShedsWhenQueueIsFull(t *testing.T) { // One job occupies the worker, one fills the single buffer slot, the // third has nowhere to go. accepted := 0 - for i := 0; i < 3; i++ { + for i := range 3 { if q.Submit(testRequest(fmt.Sprintf("at://did:plc:testuser/io.atcr.manifest/%d", i))) { accepted++ } @@ -315,7 +315,7 @@ func TestWaitDrainsAndDoesNotLeak(t *testing.T) { return nil }) - for i := 0; i < 4; i++ { + for i := range 4 { if !q.Submit(testRequest(fmt.Sprintf("at://did:plc:testuser/io.atcr.manifest/drain%d", i))) { t.Fatalf("Submit %d rejected", i) } diff --git a/pkg/appview/installscript/installscript_test.go b/pkg/appview/installscript/installscript_test.go index 3421d18..159efc6 100644 --- a/pkg/appview/installscript/installscript_test.go +++ b/pkg/appview/installscript/installscript_test.go @@ -209,7 +209,7 @@ func TestCredHelpersKeyIsRegistryNotSite(t *testing.T) { func offendingLines(s, needle string) string { var out []string - for _, line := range strings.Split(s, "\n") { + for line := range strings.SplitSeq(s, "\n") { if strings.Contains(line, needle) { out = append(out, " "+line) } diff --git a/pkg/appview/leases/manager.go b/pkg/appview/leases/manager.go index 918c398..7d85ccc 100644 --- a/pkg/appview/leases/manager.go +++ b/pkg/appview/leases/manager.go @@ -126,11 +126,9 @@ var errNotAcquired = errors.New("leases: not acquired") // could then return before the worker has even started, let alone released its // lease. func (m *Manager) Go(ctx context.Context, name string, fn func(context.Context) error) { - m.wg.Add(1) - go func() { - defer m.wg.Done() + m.wg.Go(func() { m.Run(ctx, name, fn) - }() + }) } // Wait blocks until every worker started with Go has stopped and released its diff --git a/pkg/auth/token/handler.go b/pkg/auth/token/handler.go index 9bc4c43..0a164bd 100644 --- a/pkg/auth/token/handler.go +++ b/pkg/auth/token/handler.go @@ -391,7 +391,7 @@ func collectScopes(values []string) []string { var scopes []string seen := make(map[string]bool) for _, value := range values { - for _, scope := range strings.Fields(value) { + for scope := range strings.FieldsSeq(value) { if seen[scope] { continue } diff --git a/pkg/credhelper/config_safety_test.go b/pkg/credhelper/config_safety_test.go index 531abe4..43fe496 100644 --- a/pkg/credhelper/config_safety_test.go +++ b/pkg/credhelper/config_safety_test.go @@ -258,7 +258,7 @@ func TestMigrateV2toV3_DIDCollisionIsDeterministic(t *testing.T) { }` // Repeat: a single pass can pass by luck when the bug is map-order dependent. - for i := 0; i < 50; i++ { + for i := range 50 { dir := setupConfigDir(t) writeConfigFile(t, dir, v2) @@ -297,7 +297,7 @@ func TestMigrateV2toV3_DIDCollisionIsDeterministic(t *testing.T) { func TestMigrateV2toV3_CollisionDonatesSecret(t *testing.T) { // Looped: with map-order-dependent code this is a coin flip, so a single // pass can pass by luck. - for i := 0; i < 50; i++ { + for i := range 50 { testCollisionDonatesSecret(t, i) } } @@ -394,7 +394,7 @@ func TestFindIsDeterministic(t *testing.T) { if want == nil { t.Fatal("find returned nil for a known handle") } - for i := 0; i < 50; i++ { + for i := range 50 { if got := newReg().find("shared.com"); got.DID != want.DID { t.Fatalf("iteration %d: find returned %s, want %s consistently", i, got.DID, want.DID) } diff --git a/pkg/hold/db/libsql_open_test.go b/pkg/hold/db/libsql_open_test.go index 48bfa14..8fe4071 100644 --- a/pkg/hold/db/libsql_open_test.go +++ b/pkg/hold/db/libsql_open_test.go @@ -22,7 +22,7 @@ func assertPoolSettings(t *testing.T, label string, db *sql.DB, wantJournal stri _ = c.Close() } }() - for i := 0; i < n; i++ { + for i := range n { c, err := db.Conn(ctx) if err != nil { t.Fatalf("%s: open conn %d: %v", label, i, err) diff --git a/pkg/hold/db/sqlite_store_contention_test.go b/pkg/hold/db/sqlite_store_contention_test.go index 3fc1d9c..4627f44 100644 --- a/pkg/hold/db/sqlite_store_contention_test.go +++ b/pkg/hold/db/sqlite_store_contention_test.go @@ -31,8 +31,8 @@ func makeBlocks(t *testing.T, n int, salt string) (cid.Cid, map[cid.Cid]blockfor t.Helper() blks := make(map[cid.Cid]blockformat.Block, n) var root cid.Cid - for i := 0; i < n; i++ { - b := blockformat.NewBlock([]byte(fmt.Sprintf("%s-block-%d-%s", salt, i, strings.Repeat("x", 2048)))) + for i := range n { + b := blockformat.NewBlock(fmt.Appendf(nil, "%s-block-%d-%s", salt, i, strings.Repeat("x", 2048))) blks[b.Cid()] = b if i == 0 { root = b.Cid() @@ -50,11 +50,11 @@ func writeShards(t *testing.T, sqs *SQLiteStore, writers, iters int) error { var mu sync.Mutex var firstErr error - for w := 0; w < writers; w++ { + for w := range writers { wg.Add(1) go func(w int) { defer wg.Done() - for i := 0; i < iters; i++ { + for i := range iters { salt := fmt.Sprintf("w%d-i%d", w, i) root, blks := makeBlocks(t, 12, salt) rev := fmt.Sprintf("rev-%03d-%03d", w, i) diff --git a/pkg/hold/gc/gc.go b/pkg/hold/gc/gc.go index 54890db..67bb698 100644 --- a/pkg/hold/gc/gc.go +++ b/pkg/hold/gc/gc.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "log/slog" + "maps" "net" "net/http" "net/url" @@ -136,9 +137,7 @@ func (c *auxOrphanClock) snapshot() map[string]time.Time { defer c.mu.Unlock() out := make(map[string]time.Time, len(c.since)) - for k, v := range c.since { - out[k] = v - } + maps.Copy(out, c.since) return out } diff --git a/pkg/hold/pds/carstore_contention_test.go b/pkg/hold/pds/carstore_contention_test.go index 72e0200..feb734b 100644 --- a/pkg/hold/pds/carstore_contention_test.go +++ b/pkg/hold/pds/carstore_contention_test.go @@ -75,11 +75,11 @@ func TestHoldPDSConcurrentRepoWritesAndSideTable(t *testing.T) { stop := make(chan struct{}) // Repo record writers. - for w := 0; w < writers; w++ { + for w := range writers { writeWG.Add(1) go func(w int) { defer writeWG.Done() - for i := 0; i < iters; i++ { + for i := range iters { rkey := fmt.Sprintf("w%d-layer-%03d", w, i) rec := atproto.NewLayerRecord( fmt.Sprintf("sha256:%064x", w*1000+i), @@ -97,10 +97,8 @@ func TestHoldPDSConcurrentRepoWritesAndSideTable(t *testing.T) { } // Repo readers, hitting the carstore's read transactions concurrently. - for r := 0; r < 2; r++ { - loopWG.Add(1) - go func() { - defer loopWG.Done() + for range 2 { + loopWG.Go(func() { for { select { case <-stop: @@ -112,13 +110,11 @@ func TestHoldPDSConcurrentRepoWritesAndSideTable(t *testing.T) { return } } - }() + }) } // The side subsystem, writing its own table on its own goroutine. - loopWG.Add(1) - go func() { - defer loopWG.Done() + loopWG.Go(func() { for i := 0; ; i++ { select { case <-stop: @@ -133,7 +129,7 @@ func TestHoldPDSConcurrentRepoWritesAndSideTable(t *testing.T) { return } } - }() + }) writersDone := make(chan struct{}) go func() { diff --git a/pkg/hold/pds/events_test.go b/pkg/hold/pds/events_test.go index 5122dc1..a8d7d33 100644 --- a/pkg/hold/pds/events_test.go +++ b/pkg/hold/pds/events_test.go @@ -872,7 +872,7 @@ func TestSendBackfillMsg_AbortsOnDisconnect(t *testing.T) { // The subscriber uses a 1-slot buffer with no reader so the backfill is // reliably blocked in the send when Unsubscribe fires. func TestBackfillFromDatabase_ConcurrentUnsubscribe(t *testing.T) { - for i := 0; i < 25; i++ { + for range 25 { func() { dbPath := t.TempDir() + "/events.db" broadcaster := NewEventBroadcaster("did:web:hold.example.com", 500, dbPath) @@ -880,7 +880,7 @@ func TestBackfillFromDatabase_ConcurrentUnsubscribe(t *testing.T) { ctx := context.Background() testCID, _ := cid.Decode("bafyreib2rxk3rkhh5ylyxj3x3gathxt3s32qvwj2lf3qg4kmzr6b7teqke") - for j := 0; j < 50; j++ { + for range 50 { broadcaster.Broadcast(ctx, &RepoEvent{ NewRoot: testCID, Rev: "rev", diff --git a/pkg/hold/pds/scan_broadcaster.go b/pkg/hold/pds/scan_broadcaster.go index 1b52f31..235ebd3 100644 --- a/pkg/hold/pds/scan_broadcaster.go +++ b/pkg/hold/pds/scan_broadcaster.go @@ -905,7 +905,7 @@ func (sb *ScanBroadcaster) selectSubscriberLocked() *ScanSubscriber { best := -1 bestScore := 0.0 - for i := 0; i < n; i++ { + for i := range n { idx := (sb.nextIdx + i) % n sub := sb.subscribers[idx] capacity := sub.effectiveCapacity() diff --git a/pkg/hold/pds/scan_broadcaster_concurrency_test.go b/pkg/hold/pds/scan_broadcaster_concurrency_test.go index c23e434..b84ae5c 100644 --- a/pkg/hold/pds/scan_broadcaster_concurrency_test.go +++ b/pkg/hold/pds/scan_broadcaster_concurrency_test.go @@ -761,7 +761,7 @@ func TestScanDrain_StopsAtTheSubscriberCapacity(t *testing.T) { sub.capacity = 2 var seqs []int64 - for i := 0; i < 5; i++ { + for range 5 { seqs = append(seqs, seedJob(t, sb, "sha256:backlog", originProactive)) } diff --git a/pkg/hold/pds/scan_broadcaster_stuck_test.go b/pkg/hold/pds/scan_broadcaster_stuck_test.go index 1b62848..7f877ed 100644 --- a/pkg/hold/pds/scan_broadcaster_stuck_test.go +++ b/pkg/hold/pds/scan_broadcaster_stuck_test.go @@ -520,7 +520,7 @@ func TestScanDispatchQueue_ReturnsUndeliverableJobsToPending(t *testing.T) { sub.capacity = 4 // the send buffer, not capacity, is the constraint here var seqs []int64 - for i := 0; i < 4; i++ { + for range 4 { seqs = append(seqs, seedJobWithDigest(t, sb, "sha256:burst")) } diff --git a/pkg/hold/pds/scan_broadcaster_test.go b/pkg/hold/pds/scan_broadcaster_test.go index a9b9cfc..8c4eccb 100644 --- a/pkg/hold/pds/scan_broadcaster_test.go +++ b/pkg/hold/pds/scan_broadcaster_test.go @@ -114,7 +114,7 @@ func newTestScanSubscriber(t *testing.T, sb *ScanBroadcaster, bufSize int) *Scan func seedPendingJobs(t *testing.T, sb *ScanBroadcaster, n int) { t.Helper() - for i := 0; i < n; i++ { + for i := range n { _, err := sb.db.Exec(` INSERT INTO scan_jobs (manifest_digest, repository, tag, user_did, user_handle, @@ -226,7 +226,7 @@ func TestScanUnsubscribe_MarksItsOwnJobsOnce(t *testing.T) { // The subscriber uses a 1-slot buffer with no reader so the drain is reliably // blocked in the send when Unsubscribe fires. func TestScanDrainPendingJobs_ConcurrentUnsubscribe(t *testing.T) { - for i := 0; i < 25; i++ { + for range 25 { func() { sb := newTestScanBroadcaster(t) sub := newTestScanSubscriber(t, sb, 1)