(input string)
| 1373 | } |
| 1374 | |
| 1375 | func parsePullRequestRef(input string) (string, string, int, error) { |
| 1376 | candidate := strings.TrimSpace(strings.TrimSuffix(input, "/")) |
| 1377 | if candidate == "" { |
| 1378 | return "", "", 0, fmt.Errorf("pull request reference cannot be empty") |
| 1379 | } |
| 1380 | |
| 1381 | if strings.HasPrefix(candidate, "http://") || strings.HasPrefix(candidate, "https://") { |
| 1382 | u, err := url.Parse(candidate) |
| 1383 | if err != nil { |
| 1384 | return "", "", 0, fmt.Errorf("parse url %q: %w", input, err) |
| 1385 | } |
| 1386 | if !strings.EqualFold(u.Host, "github.com") { |
| 1387 | return "", "", 0, fmt.Errorf("expected github.com host, got %s", u.Host) |
| 1388 | } |
| 1389 | segments := strings.Split(strings.Trim(u.Path, "/"), "/") |
| 1390 | if len(segments) < 4 { |
| 1391 | return "", "", 0, fmt.Errorf("expected GitHub pull request URL, got %q", input) |
| 1392 | } |
| 1393 | owner := segments[0] |
| 1394 | repo := strings.TrimSuffix(segments[1], ".git") |
| 1395 | number := 0 |
| 1396 | for i := 2; i < len(segments); i++ { |
| 1397 | if segments[i] == "pull" || segments[i] == "pulls" { |
| 1398 | if i+1 < len(segments) { |
| 1399 | if n, err := strconv.Atoi(strings.TrimSpace(segments[i+1])); err == nil && n > 0 { |
| 1400 | number = n |
| 1401 | break |
| 1402 | } |
| 1403 | } |
| 1404 | } |
| 1405 | } |
| 1406 | if owner == "" || repo == "" || number == 0 { |
| 1407 | return "", "", 0, fmt.Errorf("unable to parse pull request from %q", input) |
| 1408 | } |
| 1409 | return owner, repo, number, nil |
| 1410 | } |
| 1411 | |
| 1412 | if hash := strings.Index(candidate, "#"); hash > 0 { |
| 1413 | repoPart := strings.TrimSpace(candidate[:hash]) |
| 1414 | numberPart := strings.TrimSpace(candidate[hash+1:]) |
| 1415 | owner, repo, err := splitOwnerRepo(repoPart) |
| 1416 | if err != nil { |
| 1417 | return "", "", 0, err |
| 1418 | } |
| 1419 | number, err := strconv.Atoi(numberPart) |
| 1420 | if err != nil || number <= 0 { |
| 1421 | return "", "", 0, fmt.Errorf("invalid pull request number %q", numberPart) |
| 1422 | } |
| 1423 | return owner, repo, number, nil |
| 1424 | } |
| 1425 | |
| 1426 | if strings.Contains(candidate, "/pull/") || strings.Contains(candidate, "/pulls/") { |
| 1427 | parts := strings.Split(candidate, "/") |
| 1428 | if len(parts) >= 4 { |
| 1429 | owner := parts[0] |
| 1430 | repo := strings.TrimSuffix(parts[1], ".git") |
| 1431 | for i := 2; i < len(parts); i++ { |
| 1432 | if parts[i] == "pull" || parts[i] == "pulls" { |
no test coverage detected