From dd6f7faaa3a5242214a350e91fda41a0832d7535 Mon Sep 17 00:00:00 2001 From: marko1olo Date: Sat, 6 Jun 2026 10:28:14 +0400 Subject: [PATCH] Handle SHA-256 zero OIDs in pre-push --- pre_commit/commands/hook_impl.py | 8 ++++++-- tests/commands/hook_impl_test.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/pre_commit/commands/hook_impl.py b/pre_commit/commands/hook_impl.py index 7b806f3b8..6affccd50 100644 --- a/pre_commit/commands/hook_impl.py +++ b/pre_commit/commands/hook_impl.py @@ -14,6 +14,10 @@ Z40 = '0' * 40 +def _is_zero_oid(oid: str) -> bool: + return len(oid) in {40, 64} and oid == '0' * len(oid) + + def _run_legacy( hook_type: str, hook_dir: str | None, @@ -128,9 +132,9 @@ def _pre_push_ns( for line in stdin.decode().splitlines(): parts = line.rsplit(maxsplit=3) local_branch, local_sha, remote_branch, remote_sha = parts - if local_sha == Z40: + if _is_zero_oid(local_sha): continue - elif remote_sha != Z40 and _rev_exists(remote_sha): + elif not _is_zero_oid(remote_sha) and _rev_exists(remote_sha): return _ns( 'pre-push', color, from_ref=remote_sha, to_ref=local_sha, diff --git a/tests/commands/hook_impl_test.py b/tests/commands/hook_impl_test.py index 9aa93af53..cc77e919d 100644 --- a/tests/commands/hook_impl_test.py +++ b/tests/commands/hook_impl_test.py @@ -253,6 +253,14 @@ def test_run_ns_post_checkout(): assert ns.checkout_type == 'c' +def test_is_zero_oid(): + assert hook_impl._is_zero_oid(hook_impl.Z40) + assert hook_impl._is_zero_oid('0' * 64) + assert not hook_impl._is_zero_oid('0' * 39) + assert not hook_impl._is_zero_oid('0' * 63) + assert not hook_impl._is_zero_oid('1'.zfill(40)) + + @pytest.fixture def push_example(tempdir_factory): src = git_dir(tempdir_factory) @@ -347,6 +355,17 @@ def test_run_ns_pre_push_deleting_branch(push_example): assert ns is None +def test_run_ns_pre_push_deleting_branch_sha256(push_example): + src, src_head, clone, _ = push_example + + with cwd(clone): + args = ('origin', src) + stdin = f'(delete) {"0" * 64} refs/heads/b {src_head}'.encode() + ns = hook_impl._run_ns('pre-push', False, args, stdin) + + assert ns is None + + def test_hook_impl_main_noop_pre_push(cap_out, store, push_example): src, src_head, clone, _ = push_example