()
| 679 | |
| 680 | |
| 681 | def main() -> int: |
| 682 | args = parse_args() |
| 683 | output_dir = Path(args.output_dir) |
| 684 | csv_path = output_dir / 'commitlist.csv' |
| 685 | export_dir = output_dir / 'export' |
| 686 | contributors_path = output_dir / 'contributors.txt' |
| 687 | |
| 688 | commits = collect_commits( |
| 689 | args.base_ref, |
| 690 | args.head_ref, |
| 691 | use_merge_base=not args.direct_range, |
| 692 | ) |
| 693 | if not commits: |
| 694 | raise SystemExit( |
| 695 | f'No commits found between {args.base_ref} and {args.head_ref}.' |
| 696 | ) |
| 697 | |
| 698 | pull_requests: dict[int, PullRequestRecord] = {} |
| 699 | pr_numbers = sorted( |
| 700 | {commit.pr_number for commit in commits if commit.pr_number is not None} |
| 701 | ) |
| 702 | if args.local_only and pr_numbers: |
| 703 | print( |
| 704 | 'Warning: running in --local-only mode. PR metadata will not be fetched, ' |
| 705 | 'so category/topic fall back to Others and descriptions stay empty.', |
| 706 | file=sys.stderr, |
| 707 | ) |
| 708 | if not args.local_only and pr_numbers: |
| 709 | token = load_token(args.token) |
| 710 | if not token: |
| 711 | print( |
| 712 | 'Warning: GitHub token not found. Falling back to unauthenticated ' |
| 713 | 'GitHub API requests; this may hit rate limits on large ranges.', |
| 714 | file=sys.stderr, |
| 715 | ) |
| 716 | cache = PullRequestCache(Path(args.cache_path)) |
| 717 | cached = cache.get_many(pr_numbers) |
| 718 | missing = [ |
| 719 | number |
| 720 | for number in pr_numbers |
| 721 | if number not in cached or cached[number].title == f'PR #{number}' |
| 722 | ] |
| 723 | fetched = GitHubClient( |
| 724 | args.token or token, args.owner, args.repo |
| 725 | ).fetch_pull_requests( |
| 726 | missing, |
| 727 | batch_size=max(1, args.batch_size), |
| 728 | workers=max(1, args.workers), |
| 729 | ) |
| 730 | cache.update_many(fetched.values()) |
| 731 | pull_requests = {**cached, **fetched} |
| 732 | |
| 733 | rows, missing_prs = build_commit_rows( |
| 734 | commits, pull_requests, args.owner, args.repo |
| 735 | ) |
| 736 | contributors = sorted( |
| 737 | {commit.git_author for commit in commits if commit.git_author}, |
| 738 | key=str.casefold, |
no test coverage detected