import pickle from random import randrange from subprocess import check_output from common import set_ BITS = 10 def mask(height: int) -> int: return ((1 << height.bit_length()) - 1) >> BITS def valid(commit: str, height: int) -> bool: expected = int.from_bytes(bytes.fromhex(commit), "little") return mask(height) & (height ^ expected) == 0 # args = [] args = ["--topo-order"] original_commits = check_output(["git", "log", "--pretty=%H", *args], text=True).splitlines() N = len(original_commits) total_changes: dict[str, tuple[int, int]] = {} chosen_parents: dict[str, str | None] = {} heights: dict[str, int] = {} nheights: dict[str, int] = {} included = set() for i, commit in enumerate(reversed(original_commits)): print(f"C={i / N:6f}", flush=True) parents = check_output(["git", "log", "--pretty=%P", "-n", "1", commit], text=True).split() parents = [parent for parent in parents if parent in heights] chosen_parent = None height = 1 + max((heights[parent] for parent in parents), default=0) nheight = 1 + min((nheights[parent] for parent in parents), default=0) if nheight > mask(height) or valid(commit, height): included.add(commit) nheight = 0 ctr = set_(commit) changes = len(ctr), 1 for parent in parents: if parent in included: _parent = parent else: _parent = chosen_parents[parent] if _parent is None: continue assert _parent in included pctr = set_(_parent) pcc, pch = total_changes[parent] maybe_changes = len(pctr - ctr) + len(ctr - pctr) + pcc, pch + 1 if maybe_changes > changes: changes = maybe_changes chosen_parent = parent else: changes = 0, 1 for parent in parents: pcc, pch = total_changes[parent] maybe_changes = pcc, pch + 1 if maybe_changes > changes: changes = maybe_changes chosen_parent = parent total_changes[commit] = changes if chosen_parent is not None and chosen_parent not in included: chosen_parent = chosen_parents[chosen_parent] assert chosen_parent is None or chosen_parent in included chosen_parents[commit] = chosen_parent heights[commit] = height nheights[commit] = nheight commit = original_commits[0] commits = [] while commit is not None: commits.append(commit) commit = chosen_parents[commit] with open("/code/commits.dat", "wb") as file: pickle.dump(commits, file)