blob: 79573198e46b524e5e139b4f2ef3c2a324ab0c2b [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
nitroglycerine56acf682022-12-15 03:55:38 -08008from typing import Dict
Patrick Williams215c1c32022-01-06 20:26:26 -06009
Patrick Williamsa3db66b2022-12-04 16:27:08 -060010import libvoters.acceptable as acceptable
Andrew Jefferyed5643f2023-05-22 12:38:59 +093011from libvoters import UserChanges, changes_factory
Patrick Williamsa3db66b2022-12-04 16:27:08 -060012from libvoters.time import TimeOfDay, timestamp
13
Patrick Williams215c1c32022-01-06 20:26:26 -060014
15class subcmd:
16 def __init__(self, parser: argparse._SubParsersAction) -> None:
17 p = parser.add_parser(
18 "analyze-commits", help="Determine points for commits"
19 )
20
21 p.add_argument(
22 "--before",
23 "-b",
24 help="Before timestamp (YYYY-MM-DD)",
25 required=True,
26 )
27 p.add_argument(
28 "--after",
29 "-a",
30 help="After timestamp (YYYY-MM-DD)",
31 required=True,
32 )
33
34 p.set_defaults(cmd=self)
35
36 def run(self, args: argparse.Namespace) -> int:
37 before = timestamp(args.before, TimeOfDay.AM)
38 after = timestamp(args.after, TimeOfDay.PM)
39
Andrew Jefferyed5643f2023-05-22 12:38:59 +093040 changes_per_user: Dict[str, UserChanges] = defaultdict(changes_factory)
Patrick Williams215c1c32022-01-06 20:26:26 -060041
42 for f in sorted(os.listdir(args.dir)):
43 path = os.path.join(args.dir, f)
44 if not os.path.isfile(path):
45 continue
46
Patrick Williamsa3db66b2022-12-04 16:27:08 -060047 if not re.match(r"[0-9]*\.json", f):
Patrick Williams215c1c32022-01-06 20:26:26 -060048 continue
49
50 with open(path, "r") as file:
51 data = json.load(file)
52
53 if data["status"] != "MERGED":
54 continue
55
56 merged_at = 0
57 for c in data["comments"]:
58 if "timestamp" not in c:
59 continue
60 if "message" in c and re.match(
61 "Change has been successfully .*", c["message"]
62 ):
63 merged_at = c["timestamp"]
64
65 if merged_at == 0:
66 raise RuntimeError(f"Missing merge timestamp on {f}")
67
68 if merged_at > before or merged_at < after:
69 continue
70
71 project = data["project"]
72 id_number = data["number"]
Andrew Jefferyed5643f2023-05-22 12:38:59 +093073 username = data["owner"]["username"]
Patrick Williams215c1c32022-01-06 20:26:26 -060074
75 if not acceptable.project(project):
76 print("Rejected project:", project, id_number)
77 continue
78
79 changes = 0
80 touched_files = []
81 for file_data in sorted(
82 data["patchSets"], key=lambda x: x["number"]
83 )[-1][
84 "files"
85 ]: # type: Dict[str, Any]
86 if not acceptable.file(project, file_data["file"]):
87 continue
88 changes += int(file_data["insertions"]) + abs(
89 int(file_data["deletions"])
90 )
91 touched_files.append(file_data["file"])
92
93 if changes < 10:
94 print("Rejected for limited changes:", project, id_number)
95 continue
96
Andrew Jefferyed5643f2023-05-22 12:38:59 +093097 print(project, id_number, username)
Patrick Williams215c1c32022-01-06 20:26:26 -060098 for f in touched_files:
99 print(f" {f}")
100
Andrew Jefferyed5643f2023-05-22 12:38:59 +0930101 user = changes_per_user[username]
102 user["name"] = data["owner"]["name"]
103 user["email"] = data["owner"]["email"]
104 user["changes"].append(id_number)
Patrick Williams215c1c32022-01-06 20:26:26 -0600105
106 with open(os.path.join(args.dir, "commits.json"), "w") as outfile:
107 outfile.write(json.dumps(changes_per_user, indent=4))
108
109 return 0