searchOrgReposByQuery paginates through GitHub code-search results for the given query, deduplicates by repository full name, and returns a deterministically sorted slice of "owner/repo" strings.
(ctx context.Context, query string, verbose bool)
| 80 | // query, deduplicates by repository full name, and returns a deterministically |
| 81 | // sorted slice of "owner/repo" strings. |
| 82 | func searchOrgReposByQuery(ctx context.Context, query string, verbose bool) ([]string, error) { |
| 83 | perPage := 100 |
| 84 | page := 1 |
| 85 | seen := make(map[string]struct{}) |
| 86 | var repos []string |
| 87 | |
| 88 | for { |
| 89 | if err := waitForOrgRateLimitFn(ctx, "search", verbose); err != nil && verbose { |
| 90 | fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Continuing after search rate limit check failure: %v", err))) |
| 91 | } |
| 92 | endpoint := fmt.Sprintf("/search/code?q=%s&per_page=%d&page=%d", url.QueryEscape(query), perPage, page) |
| 93 | output, err := workflow.RunGHContext(ctx, "Searching repositories...", "api", endpoint) |
| 94 | if err != nil { |
| 95 | return nil, fmt.Errorf("failed to search organization repositories: %w", err) |
| 96 | } |
| 97 | |
| 98 | var response orgSearchResponse |
| 99 | if err := json.Unmarshal(output, &response); err != nil { |
| 100 | return nil, fmt.Errorf("failed to parse organization search results: %w", err) |
| 101 | } |
| 102 | if len(response.Items) == 0 { |
| 103 | break |
| 104 | } |
| 105 | |
| 106 | for _, item := range response.Items { |
| 107 | repo := strings.TrimSpace(item.Repository.FullName) |
| 108 | if repo == "" { |
| 109 | continue |
| 110 | } |
| 111 | if _, ok := seen[repo]; ok { |
| 112 | continue |
| 113 | } |
| 114 | seen[repo] = struct{}{} |
| 115 | repos = append(repos, repo) |
| 116 | } |
| 117 | |
| 118 | updateOrgSearchLog.Printf("Search page %d returned %d items (%d unique repos so far)", page, len(response.Items), len(repos)) |
| 119 | |
| 120 | if len(response.Items) < perPage { |
| 121 | break |
| 122 | } |
| 123 | page++ |
| 124 | } |
| 125 | |
| 126 | slices.Sort(repos) |
| 127 | updateOrgSearchLog.Printf("Org code-search complete: %d unique repos found", len(repos)) |
| 128 | return repos, nil |
| 129 | } |
| 130 | |
| 131 | // validateRepoGlobs reports an error for any empty or syntactically invalid |
| 132 | // glob pattern in the --repos flag slice. |
no test coverage detected