blob: 4939a0b40ac0f503d14fc7511cd5c82ebeafdb90 [file] [log] [blame]
Patrick Williams215c1c32022-01-06 20:26:26 -06001#!/usr/bin/python3
2
3import argparse
4import json
Patrick Williams215c1c32022-01-06 20:26:26 -06005import os
6import re
7from collections import defaultdict
Patrick Williams215c1c32022-01-06 20:26:26 -06008from typing import Any, Dict
9
Patrick Williamsa3db66b2022-12-04 16:27:08 -060010import libvoters.acceptable as acceptable
11from libvoters.time import TimeOfDay, timestamp
12
Patrick Williams215c1c32022-01-06 20:26:26 -060013
14class subcmd:
15 def __init__(self, parser: argparse._SubParsersAction) -> None:
16 p = parser.add_parser(
17 "analyze-commits", help="Determine points for commits"
18 )
19
20 p.add_argument(
21 "--before",
22 "-b",
23 help="Before timestamp (YYYY-MM-DD)",
24 required=True,
25 )
26 p.add_argument(
27 "--after",
28 "-a",
29 help="After timestamp (YYYY-MM-DD)",
30 required=True,
31 )
32
33 p.set_defaults(cmd=self)
34
35 def run(self, args: argparse.Namespace) -> int:
36 before = timestamp(args.before, TimeOfDay.AM)
37 after = timestamp(args.after, TimeOfDay.PM)
38
39 changes_per_user: Dict[str, list[int]] = defaultdict(list)
40
41 for f in sorted(os.listdir(args.dir)):
42 path = os.path.join(args.dir, f)
43 if not os.path.isfile(path):
44 continue
45
Patrick Williamsa3db66b2022-12-04 16:27:08 -060046 if not re.match(r"[0-9]*\.json", f):
Patrick Williams215c1c32022-01-06 20:26:26 -060047 continue
48
49 with open(path, "r") as file:
50 data = json.load(file)
51
52 if data["status"] != "MERGED":
53 continue
54
55 merged_at = 0
56 for c in data["comments"]:
57 if "timestamp" not in c:
58 continue
59 if "message" in c and re.match(
60 "Change has been successfully .*", c["message"]
61 ):
62 merged_at = c["timestamp"]
63
64 if merged_at == 0:
65 raise RuntimeError(f"Missing merge timestamp on {f}")
66
67 if merged_at > before or merged_at < after:
68 continue
69
70 project = data["project"]
71 id_number = data["number"]
72 user = data["owner"]["username"]
73
74 if not acceptable.project(project):
75 print("Rejected project:", project, id_number)
76 continue
77
78 changes = 0
79 touched_files = []
80 for file_data in sorted(
81 data["patchSets"], key=lambda x: x["number"]
82 )[-1][
83 "files"
84 ]: # type: Dict[str, Any]
85 if not acceptable.file(project, file_data["file"]):
86 continue
87 changes += int(file_data["insertions"]) + abs(
88 int(file_data["deletions"])
89 )
90 touched_files.append(file_data["file"])
91
92 if changes < 10:
93 print("Rejected for limited changes:", project, id_number)
94 continue
95
96 print(project, id_number, user)
97 for f in touched_files:
98 print(f" {f}")
99
100 changes_per_user[user].append(id_number)
101
102 with open(os.path.join(args.dir, "commits.json"), "w") as outfile:
103 outfile.write(json.dumps(changes_per_user, indent=4))
104
105 return 0