( ctx context.Context, token string, ref PRRef, )
| 224 | } |
| 225 | |
| 226 | func (g *gitlabProvider) FetchPullRequestDiff( |
| 227 | ctx context.Context, |
| 228 | token string, |
| 229 | ref PRRef, |
| 230 | ) (string, error) { |
| 231 | pid := gitLabPID(ref.Owner, ref.Repo) |
| 232 | |
| 233 | // Make a direct HTTP request instead of using the library's |
| 234 | // ShowMergeRequestRawDiffs, which reads the entire response |
| 235 | // into memory before returning. We use io.LimitReader to |
| 236 | // bound memory and reject diffs exceeding MaxDiffSize. |
| 237 | rawURL := fmt.Sprintf("%sprojects/%s/merge_requests/%d/raw_diffs", |
| 238 | g.client.BaseURL().String(), url.PathEscape(pid), ref.Number) |
| 239 | req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil) |
| 240 | if err != nil { |
| 241 | return "", g.wrapError(err, "create raw diffs request") |
| 242 | } |
| 243 | if token != "" { |
| 244 | req.Header.Set("Authorization", "Bearer "+token) |
| 245 | } |
| 246 | |
| 247 | resp, err := g.client.HTTPClient().Do(req) |
| 248 | if err != nil { |
| 249 | return "", g.wrapError(err, "get merge request raw diffs") |
| 250 | } |
| 251 | defer resp.Body.Close() |
| 252 | |
| 253 | if resp.StatusCode != http.StatusOK { |
| 254 | if rlErr := checkRateLimitError(resp, g.clock, "RateLimit-Reset"); rlErr != nil { |
| 255 | return "", rlErr |
| 256 | } |
| 257 | body, readErr := io.ReadAll(io.LimitReader(resp.Body, 8192)) |
| 258 | if readErr != nil { |
| 259 | return "", g.wrapError( |
| 260 | xerrors.Errorf("unexpected status %d", resp.StatusCode), |
| 261 | "get merge request raw diffs", |
| 262 | ) |
| 263 | } |
| 264 | return "", g.wrapError( |
| 265 | xerrors.Errorf("unexpected status %d: %s", resp.StatusCode, strings.TrimSpace(string(body))), |
| 266 | "get merge request raw diffs", |
| 267 | ) |
| 268 | } |
| 269 | |
| 270 | buf, err := io.ReadAll(io.LimitReader(resp.Body, MaxDiffSize+1)) |
| 271 | if err != nil { |
| 272 | return "", g.wrapError(err, "read merge request raw diffs") |
| 273 | } |
| 274 | if len(buf) > MaxDiffSize { |
| 275 | return "", ErrDiffTooLarge |
| 276 | } |
| 277 | return string(buf), nil |
| 278 | } |
| 279 | |
| 280 | // compareResponse is the subset of GitLab's compare endpoint response |
| 281 | // that we need. We decode manually (instead of using the library) so |
nothing calls this directly
no test coverage detected