1*58e378d5SPatrick Williams#!/usr/bin/python3 2*58e378d5SPatrick Williams 3*58e378d5SPatrick Williamsimport argparse 4*58e378d5SPatrick Williamsimport json 5*58e378d5SPatrick Williamsimport os 6*58e378d5SPatrick Williamsimport re 7*58e378d5SPatrick Williamsfrom typing import Set, Tuple 8*58e378d5SPatrick Williams 9*58e378d5SPatrick Williamsimport libvoters.acceptable as acceptable 10*58e378d5SPatrick Williams 11*58e378d5SPatrick Williams 12*58e378d5SPatrick Williamsclass subcmd: 13*58e378d5SPatrick Williams def __init__(self, parser: argparse._SubParsersAction) -> None: 14*58e378d5SPatrick Williams p = parser.add_parser( 15*58e378d5SPatrick Williams "verify-files", 16*58e378d5SPatrick Williams help="Check all files against `acceptable` settings.", 17*58e378d5SPatrick Williams ) 18*58e378d5SPatrick Williams p.set_defaults(cmd=self) 19*58e378d5SPatrick Williams 20*58e378d5SPatrick Williams def run(self, args: argparse.Namespace) -> int: 21*58e378d5SPatrick Williams data_path: str = args.dir 22*58e378d5SPatrick Williams 23*58e378d5SPatrick Williams if not os.path.exists(data_path) or not os.path.isdir(data_path): 24*58e378d5SPatrick Williams print( 25*58e378d5SPatrick Williams f"Data directory {data_path} does not exist or is not a directory." 26*58e378d5SPatrick Williams ) 27*58e378d5SPatrick Williams return 1 28*58e378d5SPatrick Williams 29*58e378d5SPatrick Williams # Set to store unique (project, file) pairs 30*58e378d5SPatrick Williams unique_files: Set[Tuple[str, str]] = set() 31*58e378d5SPatrick Williams rejected_projects: Set[str] = set() 32*58e378d5SPatrick Williams 33*58e378d5SPatrick Williams # Read all JSON files from data directory 34*58e378d5SPatrick Williams for filename in sorted(os.listdir(data_path)): 35*58e378d5SPatrick Williams if not re.match(r"[0-9]+\.json", filename): 36*58e378d5SPatrick Williams continue 37*58e378d5SPatrick Williams 38*58e378d5SPatrick Williams file_path = os.path.join(data_path, filename) 39*58e378d5SPatrick Williams if not os.path.isfile(file_path): 40*58e378d5SPatrick Williams continue 41*58e378d5SPatrick Williams 42*58e378d5SPatrick Williams try: 43*58e378d5SPatrick Williams with open(file_path, "r") as f: 44*58e378d5SPatrick Williams data = json.load(f) 45*58e378d5SPatrick Williams 46*58e378d5SPatrick Williams project = data.get("project", "") 47*58e378d5SPatrick Williams if not project: 48*58e378d5SPatrick Williams continue 49*58e378d5SPatrick Williams 50*58e378d5SPatrick Williams # Check if project is acceptable 51*58e378d5SPatrick Williams if not acceptable.project(project): 52*58e378d5SPatrick Williams if project not in rejected_projects: 53*58e378d5SPatrick Williams print(f"Rejected project: {project}") 54*58e378d5SPatrick Williams rejected_projects.add(project) 55*58e378d5SPatrick Williams continue 56*58e378d5SPatrick Williams 57*58e378d5SPatrick Williams # Extract files from the last patchSet 58*58e378d5SPatrick Williams patch_sets = data.get("patchSets", []) 59*58e378d5SPatrick Williams if patch_sets: 60*58e378d5SPatrick Williams last_patch_set = sorted( 61*58e378d5SPatrick Williams patch_sets, key=lambda x: x["number"] 62*58e378d5SPatrick Williams )[-1] 63*58e378d5SPatrick Williams files = last_patch_set.get("files", []) 64*58e378d5SPatrick Williams for file_data in files: 65*58e378d5SPatrick Williams file_name = file_data.get("file", "") 66*58e378d5SPatrick Williams if file_name: 67*58e378d5SPatrick Williams unique_files.add((project, file_name)) 68*58e378d5SPatrick Williams 69*58e378d5SPatrick Williams except (json.JSONDecodeError, KeyError) as e: 70*58e378d5SPatrick Williams print(f"Error processing {filename}: {e}") 71*58e378d5SPatrick Williams continue 72*58e378d5SPatrick Williams 73*58e378d5SPatrick Williams # Verify each unique file 74*58e378d5SPatrick Williams for project, file_name in sorted(unique_files): 75*58e378d5SPatrick Williams result = acceptable.file(project, file_name) 76*58e378d5SPatrick Williams print(f"{project}:{file_name} -> {result}") 77*58e378d5SPatrick Williams 78*58e378d5SPatrick Williams return 0 79