gogcli/internal/cmd/paging.go
salmonumbrella 3371e3f3ad
feat(cli): agent ergonomics + gmail watch exclude labels (#201)
* feat(cli): improve agent ergonomics

* fix(cli): address code review findings

- Fix nil pointer dereference in confirmDestructive when flags is nil
- Deduplicate dry-run logic by delegating to dryRunExit
- Remove deprecated net.Error.Temporary() call (dead since Go 1.18)
- Add unit tests for resolveTasklistID and resolveCalendarID

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve PR #201 conflicts and follow-ups (#201) (thanks @salmonumbrella)

* fix: resolve rebase fallout for PR #201 landing (#201) (thanks @salmonumbrella)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 03:09:49 +01:00

44 lines
997 B
Go

package cmd
import (
"fmt"
"strings"
)
const emptyResultsExitCode = 3
func failEmptyExit(failEmpty bool) error {
if !failEmpty {
return nil
}
return &ExitError{Code: emptyResultsExitCode, Err: nil}
}
// collectAllPages keeps calling fetch until it returns an empty next page token.
// It guards against pagination loops by tracking seen page tokens.
func collectAllPages[T any](startPageToken string, fetch func(pageToken string) ([]T, string, error)) ([]T, error) {
pageToken := strings.TrimSpace(startPageToken)
seen := map[string]bool{}
var out []T
for i := 0; i < 10_000; i++ {
if seen[pageToken] {
return nil, fmt.Errorf("pagination loop: repeated page token %q", pageToken)
}
seen[pageToken] = true
items, next, err := fetch(pageToken)
if err != nil {
return nil, err
}
out = append(out, items...)
next = strings.TrimSpace(next)
if next == "" {
return out, nil
}
pageToken = next
}
return nil, fmt.Errorf("pagination exceeded max pages")
}