import bpy, gpu, time
gpu.init()
bpy.ops.preferences.addon_enable(module='bl_ext.user_default.hardops')
from bl_ext.user_default.hardops.utility import updater, addon
pref = addon.preference()
print("\n=== operator registered ===")
assert hasattr(bpy.ops.hops, 'fork_update'), 'HOPS_OT_ForkUpdate not registered'
print("hops.fork_update present")
print("\n=== checkout detection ===")
print("addon_path:", updater.addon_path())
assert updater.is_fork_checkout(), 'addon dir is not detected as a git checkout'
ok, head, _ = updater._git('rev-parse', 'HEAD')
print("local HEAD:", head)
print("\n=== remote_head per remote ===")
for remote in updater.FORK_REMOTES:
t = time.time()
sha = updater.remote_head(remote)
print(f" {remote:6} -> {sha or '(unreachable)'} [{time.time()-t:.1f}s]")
print("\n=== have_object ===")
assert updater.have_object(head) is True
assert updater.have_object('0' * 40) is False
print("have_object discriminates")
print("\n=== check_fork: up to date / ahead is NOT an update ===")
remote, sha = updater.check_fork()
print("check_fork ->", remote, sha)
assert remote is None, f'reported an update while in sync: {remote} {sha}'
print("\n=== check_fork: unseen remote commit IS an update ===")
real_remote_head = updater.remote_head
updater.remote_head = lambda r: 'd' * 40 if r == 'p2p' else ''
try:
remote, sha = updater.check_fork()
print("check_fork ->", remote, sha)
assert remote == 'p2p' and sha == 'd' * 40, (remote, sha)
finally:
updater.remote_head = real_remote_head
print("detects an unseen commit")
print("\n=== threaded check does not touch bpy from the thread ===")
pref.check_update = True
updater.check_for_update((26, 1, 3))
deadline = time.time() + 180
while updater._result is None and time.time() < deadline:
time.sleep(0.5)
assert updater._result is not None, 'worker never produced a result'
print("worker result:", updater._result)
# timers do not fire in --background, so drain by hand as the main thread would
assert updater._drain() is None, 'drain asked to poll again despite a result'
print("needs_update :", repr(pref.needs_update))
print("fork_update :", pref.fork_update)
print("fork_remote :", repr(pref.fork_remote))
print("\n=== pull refuses a dirty tree ===")
ok, out, _ = updater._git('status', '--porcelain')
print("dirty entries:", len(out.splitlines()))
ok, message = updater.pull('forge')
print("pull ->", ok, message)
if out:
assert ok is False and 'Local changes' in message, message
print("dirty tree correctly refused")
else:
assert ok, message
print("clean tree pulled:", message)
print("\n=== operator runs end to end ===")
result = bpy.ops.hops.fork_update(remote='forge')
print("operator ->", result)
assert result == {'FINISHED'}, result
print("\nALL CHECKS PASSED")