|  | #!/usr/bin/env python3 | 
|  |  | 
|  | # The script is used for finding PRs that have a GIT revision that | 
|  | # mentiones the PR and are not closed.  It's done by iterating all | 
|  | # comments of a PR and finding GIT commit entries. | 
|  |  | 
|  | """ | 
|  | Sample output of the script: | 
|  | Bugzilla URL page size: 50 | 
|  | HINT: bugs with following comment are ignored: Can the bug be marked as resolved? | 
|  |  | 
|  | Bug URL                                              GIT commits                   known-to-fail                           known-to-work                           Bug summary | 
|  | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88129   master                                                                                                        Two blockage insns are emited in the function epilogue | 
|  | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88122   master                                                                                                        [9 Regression] g++ ICE: internal compiler error: Segmentation fault | 
|  | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88084   master                                                                                                        basic_string_view::copy doesn't use Traits::copy | 
|  | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88083   master                                                                                                        ICE in find_constant_pool_ref_1, at config/s390/s390.c:8231 | 
|  | ... | 
|  | Bugzilla lists: | 
|  | https://gcc.gnu.org/bugzilla/buglist.cgi?bug_id=88129,88122,88084,88083,88074,88073,88071,88070,88051,88018,87985,87955,87926,87917,87913,87898,87895,87874,87871,87855,87853,87826,87824,87819,87818,87799,87793,87789,87788,87787,87754,87725,87674,87665,87649,87647,87645,87625,87611,87610,87598,87593,87582,87566,87556,87547,87544,87541,87537,87528 | 
|  | https://gcc.gnu.org/bugzilla/buglist.cgi?bug_id=87486 | 
|  | """ | 
|  |  | 
|  | import argparse | 
|  | import json | 
|  |  | 
|  | import requests | 
|  |  | 
|  | base_url = 'https://gcc.gnu.org/bugzilla/rest.cgi/' | 
|  | statuses = ['UNCONFIRMED', 'ASSIGNED', 'SUSPENDED', 'NEW', 'WAITING', 'REOPENED'] | 
|  | regex = '(.*\[)([0-9\./]*)( [rR]egression])(.*)' | 
|  | closure_question = 'Can the bug be marked as resolved?' | 
|  | start_page = 20 | 
|  | url_page_size = 50 | 
|  |  | 
|  | def get_branches_by_comments(comments): | 
|  | versions = set() | 
|  | for c in comments: | 
|  | text = c['text'] | 
|  | lines = text.split('\n') | 
|  | if 'URL: https://gcc.gnu.org/viewcvs' in text: | 
|  | version = 'master' | 
|  | for line in lines: | 
|  | if 'branches/gcc-' in line: | 
|  | parts = line.strip().split('/') | 
|  | parts = parts[1].split('-') | 
|  | assert len(parts) == 3 | 
|  | version = parts[1] | 
|  | break | 
|  | versions.add(version) | 
|  | else: | 
|  | for line in lines: | 
|  | if line.startswith('The ') and 'branch has been updated' in line: | 
|  | version = 'master' | 
|  | name = line.strip().split(' ')[1] | 
|  | if '/' in name: | 
|  | name = name.split('/')[1] | 
|  | assert '-' in name | 
|  | version = name.split('-')[1] | 
|  | versions.add(version) | 
|  | break | 
|  | return versions | 
|  |  | 
|  | def get_bugs(query): | 
|  | u = base_url + 'bug' | 
|  | r = requests.get(u, params = query) | 
|  | return r.json()['bugs'] | 
|  |  | 
|  | def search(): | 
|  | chunk = 1000 | 
|  | ids = [] | 
|  | print('%-30s%-30s%-40s%-40s%-60s' % ('Bug URL', 'GIT commits', 'known-to-fail', 'known-to-work', 'Bug summary')) | 
|  | for i in range(start_page, 0, -1): | 
|  | # print('offset: %d' % (i * chunk), flush = True) | 
|  | bugs = get_bugs({'bug_status': statuses, 'limit': chunk, 'offset': i * chunk}) | 
|  | for b in sorted(bugs, key = lambda x: x['id'], reverse = True): | 
|  | id = b['id'] | 
|  |  | 
|  | fail = b['cf_known_to_fail'] | 
|  | work = b['cf_known_to_work'] | 
|  |  | 
|  | u = base_url + 'bug/' + str(id) + '/comment' | 
|  | r = requests.get(u).json() | 
|  | keys = list(r['bugs'].keys()) | 
|  | assert len(keys) == 1 | 
|  | comments = r['bugs'][keys[0]]['comments'] | 
|  | skip = False | 
|  | for c in comments: | 
|  | if closure_question in c['text']: | 
|  | skip = True | 
|  | break | 
|  | if skip: | 
|  | continue | 
|  |  | 
|  | branches = sorted(list(get_branches_by_comments(comments)), | 
|  | key=lambda b: 999 if b is 'master' else int(b)) | 
|  | if branches: | 
|  | branches_str = ','.join(branches) | 
|  | print('%-30s%-30s%-40s%-40s%-60s' % ('https://gcc.gnu.org/PR%d' % id, branches_str, fail, work, b['summary']), flush=True) | 
|  | ids.append(id) | 
|  |  | 
|  | # print all URL lists | 
|  | print('\nBugzilla lists:') | 
|  | while len(ids) > 0: | 
|  | print('https://gcc.gnu.org/bugzilla/buglist.cgi?bug_id=%s' % ','.join([str(x) for x in ids[:url_page_size]])) | 
|  | ids = ids[url_page_size:] | 
|  |  | 
|  | print('Bugzilla URL page size: %d' % url_page_size) | 
|  | print('HINT: bugs with following comment are ignored: %s\n' % closure_question) | 
|  |  | 
|  | parser = argparse.ArgumentParser(description='') | 
|  |  | 
|  | args = parser.parse_args() | 
|  | search() |