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