76 lines
2.6 KiB
Python
76 lines
2.6 KiB
Python
import pickle
|
|
from random import randrange
|
|
from subprocess import check_output
|
|
|
|
from common import set_
|
|
|
|
BITS = 2
|
|
|
|
|
|
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)
|