import importlib.util from pathlib import Path import subprocess import pytest SCRIPT = Path(__file__).parents[1] / "scripts/install_shared_generated_guard.py" spec = importlib.util.spec_from_file_location("shared_guard", SCRIPT) guard = importlib.util.module_from_spec(spec) spec.loader.exec_module(guard) def repository(tmp_path): repo = tmp_path / "repo" repo.mkdir() subprocess.run(["git", "init", str(repo)], check=True, capture_output=True) hooks = tmp_path / "shared-hooks" hooks.mkdir() subprocess.run(["git", "-C", str(repo), "config", "core.hooksPath", str(hooks)], check=True) return repo, hooks def test_real_shared_hook_rejects_generated_only_and_retains_other_hooks(tmp_path): repo, hooks = repository(tmp_path) other = hooks / "prepare-commit-msg" other.write_text("# existing owner hook\n") before = other.read_bytes() assert guard.install(repo)["status"] == "missing" assert not (hooks / "pre-commit").exists() assert guard.install(repo, True)["changed"] assert not guard.install(repo, True)["changed"] (repo / "WORK-RECORDS.md").write_text("derived\n") subprocess.run(["git", "-C", str(repo), "add", "WORK-RECORDS.md"], check=True) assert subprocess.run([str(hooks / "pre-commit")], cwd=repo, capture_output=True).returncode == 1 (repo / "implementation.py").write_text("print('source')\n") subprocess.run(["git", "-C", str(repo), "add", "implementation.py"], check=True) assert subprocess.run([str(hooks / "pre-commit")], cwd=repo, capture_output=True).returncode == 0 assert other.read_bytes() == before def test_foreign_or_redirected_guard_is_never_replaced(tmp_path): repo, hooks = repository(tmp_path) hook = hooks / "pre-commit" hook.write_text("owner implementation\n") with pytest.raises(ValueError): guard.install(repo, True) assert hook.read_text() == "owner implementation\n" hook.unlink() private = tmp_path / "unrelated" private.write_text("retained\n") hook.symlink_to(private) with pytest.raises(ValueError): guard.install(repo, True) assert private.read_text() == "retained\n" def test_reviewed_scanner_composition_is_preserved(tmp_path): repo, hooks = repository(tmp_path) content = (SCRIPT.parents[1] / 'docs/changes/CUST-WP-0080/secret-hooks-pre-commit').read_bytes() hook = hooks / 'pre-commit' hook.write_bytes(content) hook.chmod(0o755) assert not guard.install(repo, True)['changed'] assert hook.read_bytes() == content hook.write_bytes(content + b'\n# unreviewed revision\n') with pytest.raises(ValueError): guard.install(repo, True) @pytest.mark.parametrize("existing_local", [False, True]) def test_make_install_recognizes_existing_shared_guard(tmp_path, existing_local): import shutil repo, hooks = repository(tmp_path) source = SCRIPT.parents[1] shutil.copyfile(source / "Makefile", repo / "Makefile") (repo / "scripts").mkdir() for name in ("install_shared_generated_guard.py", "check_generated_only_commit.py", "generated-pre-commit.sh"): shutil.copyfile(source / "scripts" / name, repo / "scripts" / name) if existing_local: hooks = repo / ".git" / "hooks" subprocess.run(["git", "-C", str(repo), "config", "core.hooksPath", str(hooks)], check=True) shutil.copyfile(source / "scripts/generated-pre-commit.sh", hooks / "pre-commit") (hooks / "pre-commit").chmod(0o755) other = hooks / "prepare-commit-msg" other.write_text("owner hook\n") for _ in range(2): result = subprocess.run(["make", "generated-commit-hook"], cwd=repo, capture_output=True, text=True) assert result.returncode == 0, result.stderr assert other.read_text() == "owner hook\n" (repo / "WORK-RECORDS.md").write_text("generated\n") subprocess.run(["git", "-C", str(repo), "add", "WORK-RECORDS.md"], check=True) assert subprocess.run([str(hooks / "pre-commit")], cwd=repo, capture_output=True).returncode == 1 def test_reviewed_hook_generation_upgrade_preserves_scanner(tmp_path): repo, hooks = repository(tmp_path) original = (SCRIPT.parents[1] / 'docs/changes/CUST-WP-0080/secret-hooks-pre-commit').read_bytes() hook = hooks / 'pre-commit' hook.write_bytes(original) hook.chmod(0o755) assert guard.install(repo, True, enable_generation=True)['changed'] marker = b'python3 /home/worsch/the-custodian/scripts/run_generated_work_records_hook.py\n' assert hook.read_bytes().replace(marker, b'') == original assert not guard.install(repo, True, enable_generation=True)['changed'] (repo / 'WORK-RECORDS.md').write_text('generated only') subprocess.run(['git', '-C', str(repo), 'add', 'WORK-RECORDS.md'], check=True) assert subprocess.run([str(hook)], cwd=repo, capture_output=True).returncode == 1