[go: nahoru, domu]

blob: c4b9f1247061ecce28640cff48cc991a1a16f3f2 [file] [log] [blame]
Tiem Song2b49aaf2022-08-23 15:41:00 -07001#!/usr/bin/env python3
2
3# Future improvements:
4# - link bugs and code references
5# - handle multiple bug references per line (currently only fetches one)
6# - fetch more than the first ~900 entries from Buganizer
7# - check if CLI tool is available + authenticated
8
9import pathlib, re, subprocess
10
11outfile = "closed_bugs.csv"
12
13print("Searching code for bug references")
14androidx_root = pathlib.Path(__file__).parent.parent.resolve()
15grep_cmd = subprocess.run(
16 ["egrep",
17
18 # -I excludes binary files
19 # -i case insensitive search
20 # -n include line numbers
21 # -r recursive
22 "-Iinr",
23
24 # regex for buganizer format ("b/123456789")
25 "b\/[[:digit:]]{8,9}",
26
27 # Files and directories to include and exclude
28 "--exclude-dir=.idea",
29 "--include=*.gradle",
30 "--include=*.java",
31 "--include=*.kt",
32 "--include=*.xml",
33
34 # Search all of the AndroidX repo checkout
35 f"{androidx_root}"
36 ],
37 capture_output=True,
38 text=True
39)
40raw_output_lines = grep_cmd.stdout.split("\n")
41
42print("Cleaning up search results")
43bug_dict = {} # mapping of bug id to list of filename + line number
44for line in raw_output_lines:
45 regex_result = re.search('b\/[0-9]{8,9}', line)
46 if regex_result is not None:
47 bug_id = regex_result.group(0).removeprefix("b/")
48 file = line.split(":")[0].removeprefix(str(androidx_root))
49 linenum = line.split(":")[1]
50
51 if bug_id in bug_dict:
52 matching_files = bug_dict[bug_id]
53 else:
54 matching_files = set()
55 matching_files.add(f"{file}:{linenum}")
56 bug_dict[bug_id] = matching_files
57print(f"Found {len(bug_dict)} bugs")
58
59# Create bug id query string.
60# The CLI tool fails if there are too many bugs (>900?); only use the first 900.
61bug_ids = list(bug_dict.keys())
62bug_ids.sort()
63joined_ids = "|".join(bug_ids[0:899])
64
65# Query buganizer to determine which of the given bugs are closed.
66# Store the issue, reporter, and assignee of the matching [closed] bugs.
67print("Querying Buganizer to find how many of these bugs are resolved")
68bugged_cmd = subprocess.run(
69 ["bugged", "search", f"id:({joined_ids})", "status:closed", "--columns=issue,reporter,assignee"],
70 capture_output=True,
71 text=True # capture output as String instead of byte sequence
72)
73closed_bug_list = bugged_cmd.stdout.split("\n")
74
75# Remove header and trailing rows of Buganizer query result
76closed_bug_list.pop(0)
77closed_bug_list.pop()
78print(f"{len(closed_bug_list)} have been resolved")
79
80# Combine buganizer results with file search results and write to CSV
81csv_str = "bug_id,reporter,assignee,files\n"
82for line in closed_bug_list:
83 elements = re.split(" +", line)
84 bug_id = elements[0]
85 reporter = elements[1]
86 assignee = elements[2]
87 matching_files = bug_dict[bug_id]
88 line_str = f"b/{bug_id},{reporter},{assignee},"
89
90 # The list of matching file(s) are enclosed in double quotes to preserve \n in the csv
91 line_str += ("\"" + "\n".join(matching_files) + "\"")
92
93 csv_str += line_str + "\n"
94
95print(csv_str, file=open(outfile, 'w'))
96print(f"Wrote results to {outfile}")