Add regression tests for the git hook root guard

Executes the shipped snippet directly (extracted from the rebuild
body text) rather than a hand copy that could quietly drift from it,
covering both the rejected case (a marker pointing outside the repo)
and the case the guard must not break (a subdirectory scoped root).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
This commit is contained in:
ayushcodes10andClaude Sonnet 5 committed 2026-09-11 15:13:51 +05:30
1 parent 31aa4d4e9d
commit 5976f7122a
1 file changed
+51
+51
View File
@@ -2,6 +2,7 @@
import os
import shutil
import subprocess
import textwrap
from types import SimpleNamespace
from pathlib import Path
import pytest
@@ -332,6 +333,56 @@ def test_rebuild_bodies_with_graphify_root_are_valid_python():
ast.parse(body)
def _extract_root_resolution(body: str) -> str:
"""Pull the `.graphify_root` -> `_root` snippet out of a rebuild body, so a
test can execute the shipped logic itself rather than a hand copy that could
quietly drift from it."""
match = re.search(r"( _root = Path\('\.'\).*?)\n _rebuild_code\(", body, re.DOTALL)
assert match, "root resolution snippet not found"
return textwrap.dedent(match.group(1))
@pytest.mark.parametrize(
"name,body",
[("post-commit", _REBUILD_BODY_COMMIT), ("post-checkout", _REBUILD_BODY_CHECKOUT)],
)
def test_rebuild_bodies_reject_an_out_of_repo_graphify_root(name, body, tmp_path, monkeypatch):
"""#3265: `.graphify_root` sits inside graphify-out/, a directory the
documented team workflow says to commit, so its contents are checkout
controlled. Without a bound, a value planted there by a malicious fork or PR
(an absolute path outside the repository) would steer the rebuild -- and so
what gets read, and what gets written into the same committed graphify-out/
-- to wherever the checkout names, not the repository the hook was installed
into. The recovered root must stay inside the working tree the hook actually
runs from."""
repo = tmp_path / "repo"
outside = tmp_path / "outside"
(repo / "graphify-out").mkdir(parents=True)
outside.mkdir()
(repo / "graphify-out" / ".graphify_root").write_text(str(outside), encoding="utf-8")
monkeypatch.chdir(repo)
ns = {"Path": Path, "os": os}
exec(compile(_extract_root_resolution(body), "<rebuild_body>", "exec"), ns)
assert ns["_root"].resolve() == repo.resolve(), f"{name} honoured an out-of-repo root"
@pytest.mark.parametrize(
"name,body",
[("post-commit", _REBUILD_BODY_COMMIT), ("post-checkout", _REBUILD_BODY_CHECKOUT)],
)
def test_rebuild_bodies_honour_an_in_repo_graphify_root(name, body, tmp_path, monkeypatch):
"""The legitimate case the #3265 guard must not break: a subdirectory-scoped
root (#1173) is still recovered."""
repo = tmp_path / "repo"
(repo / "graphify-out").mkdir(parents=True)
(repo / "backend").mkdir()
(repo / "graphify-out" / ".graphify_root").write_text("backend", encoding="utf-8")
monkeypatch.chdir(repo)
ns = {"Path": Path, "os": os}
exec(compile(_extract_root_resolution(body), "<rebuild_body>", "exec"), ns)
assert ns["_root"].resolve() == (repo / "backend").resolve(), f"{name} lost the scoped root"
@pytest.mark.parametrize(
"name,body",
[("post-commit", _REBUILD_BODY_COMMIT), ("post-checkout", _REBUILD_BODY_CHECKOUT)],