Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions tests/agents/hooks/test_cleanup_worktrees.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import json
from pathlib import Path
import shlex
import shutil
import subprocess
import sys

import pytest

from tests.agents.hooks.cleanup_worktrees_runtime import SCRIPT, branches, cleanup, git, task_worktree
from tests.runtime import real_git

import herdr_ownership
import session_store
Expand All @@ -26,8 +26,7 @@ def test_a_merged_clean_worktree_and_its_branch_are_removed(primary: Path, merge
def test_removal_does_not_repeat_gits_cleanliness_check(primary: Path, merged: dict[str, str], tmp_path: Path) -> None:
path = task_worktree(primary, "feat/done")
merged["feat/done"] = git("rev-parse", "HEAD", cwd=path)
executable = shutil.which("git")
assert executable
executable = real_git()
wrapper = tmp_path / "bin/git"
wrapper.write_text(
'#!/bin/sh\ncase " $* " in *" worktree remove "*)\n'
Expand Down
11 changes: 4 additions & 7 deletions tests/agents/hooks/test_cleanup_worktrees_isolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import pytest_mock

from tests.agents.hooks.cleanup_worktrees_runtime import branches, cleanup, git, task_worktree
from tests.runtime import real_git

import cleanup_worktrees

Expand Down Expand Up @@ -37,8 +38,7 @@ def test_lane_status_never_runs_a_filter_from_raced_admin_configuration(
readme.write_text("base\n")
index_time = (admin / "index").stat().st_mtime_ns
os.utime(readme, ns=(index_time, index_time))
executable = shutil.which("git")
assert executable
executable = real_git()
rewrite = ""
if planted in {"commondir", "both"}:
rewrite += f"printf '%s' {shlex.quote(str(fake))} > {shlex.quote(str(admin / 'commondir'))}\n"
Expand Down Expand Up @@ -241,12 +241,10 @@ def test_lane_fsmonitor_is_never_executed_and_git_and_gh_run_from_the_primary(
git("config", *(["--worktree"] if config == "worktree" else []), "core.fsmonitor", str(monitor), cwd=path)
discovery = tmp_path / "lane-discovery"
for name in ("git", "gh"):
executable = shutil.which(name)
assert executable
executable = real_git() if name == "git" else str(tmp_path / "original-gh")
wrapper = tmp_path / "bin" / name
if name == "gh":
wrapper.rename(tmp_path / "original-gh")
executable = str(tmp_path / "original-gh")
wrapper.write_text(
f'#!/bin/sh\ncase "$PWD" in {shlex.quote(str(path))}*|{shlex.quote(str(current))}*) '
f'touch {shlex.quote(str(discovery))}; exit 99;; esac\nexec {shlex.quote(executable)} "$@"\n'
Expand Down Expand Up @@ -298,8 +296,7 @@ def test_a_planted_git_entry_inside_a_lane_is_neither_current_nor_primary(
git("init", "--quiet", cwd=nested)
monkeypatch.setenv("HOME", str(home))
marker = tmp_path / "nested-git-ran"
executable = shutil.which("git")
assert executable
executable = real_git()
wrapper = tmp_path / "bin/git"
wrapper.write_text(
f'#!/bin/sh\nif [ "$PWD" = {shlex.quote(str(nested))} ]; then '
Expand Down
9 changes: 3 additions & 6 deletions tests/agents/hooks/test_cleanup_worktrees_trust.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import os
from pathlib import Path
import shlex
import shutil
import tempfile
from collections.abc import Iterator

Expand All @@ -17,6 +16,7 @@
git,
task_worktree,
)
from tests.runtime import real_git

import cleanup_worktrees

Expand Down Expand Up @@ -55,13 +55,11 @@ def herdr_lane(primary: Path) -> Path:
def record_commands(tmp_path: Path, forbidden: Path) -> Path:
marker = tmp_path / "untrusted-command"
for name in ("git", "gh"):
executable = shutil.which(name)
assert executable
executable = real_git() if name == "git" else str(tmp_path / "original-gh")
wrapper = tmp_path / "bin" / name
if name == "gh":
original = tmp_path / "original-gh"
wrapper.rename(original)
executable = str(original)
wrapper.write_text(
f'#!/bin/sh\nprintf "%s %s %s\\n" "$PWD" {name} "$*" >> {shlex.quote(str(tmp_path / "commands"))}\n'
f'case "$PWD $*" in *{shlex.quote(str(forbidden))}*) '
Expand Down Expand Up @@ -210,8 +208,7 @@ def test_git_removal_is_isolated_and_herdr_only_closes_the_workspace(
lane = task_worktree(primary, "feat/done")
worktree = next(tree for tree in cleanup_worktrees.linked_worktrees(primary) if tree.path == lane)
# The process wrapper rejects any invocation missing the required isolation.
executable = shutil.which("git")
assert executable
executable = real_git()
wrapper = tmp_path / "bin/git"
wrapper.write_text(
'#!/bin/sh\ncase " $* " in *" worktree remove "*)\n'
Expand Down
9 changes: 9 additions & 0 deletions tests/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
StubWriter = Callable[[str, str], Path]


def real_git() -> str:
"""Resolve Git before installing a PATH wrapper that delegates to it."""
result = subprocess.run(["git", "--exec-path"], check=True, capture_output=True, text=True, timeout=10)
# /usr/bin/git on macOS redispatches through PATH; git-core/git is the actual binary.
executable = (Path(result.stdout.strip()) / "git").resolve()
assert executable.is_file()
return str(executable)


def load_script_module(relative_path: str, module_name: str) -> ModuleType:
"""Load a trusted repository module for direct behavior tests."""
spec = util.spec_from_file_location(module_name, REPO_ROOT / relative_path)
Expand Down
41 changes: 41 additions & 0 deletions tests/test_git_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Git wrappers delegate without re-entering PATH-based platform shims."""

import os
from pathlib import Path
import shlex
import subprocess

import pytest

from tests.runtime import real_git


@pytest.mark.parametrize("shim_first", [True, False])
def test_git_wrapper_bypasses_path_lookup_in_platform_shims(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, shim_first: bool
) -> None:
exec_path = subprocess.run(["git", "--exec-path"], check=True, capture_output=True, text=True).stdout.strip()
binary = Path(exec_path) / "git"
expected = subprocess.run([str(binary), "--version"], check=True, capture_output=True, text=True).stdout
shim = tmp_path / "shim"
shim.mkdir()
(shim / "git").write_text(
'#!/bin/sh\nif [ "$1" = --exec-path ]; then\n'
f"printf '%s\\n' {shlex.quote(exec_path)}\n"
'else\nexec git "$@"\nfi\n'
)
(shim / "git").chmod(0o755)
directories = [str(shim), str(binary.parent)]
if not shim_first:
directories.reverse()
monkeypatch.setenv("PATH", os.pathsep.join(directories))
executable = real_git()
wrapper = tmp_path / "wrapper"
wrapper.mkdir()
(wrapper / "git").write_text(f'#!/bin/sh\nexec {shlex.quote(executable)} "$@"\n')
(wrapper / "git").chmod(0o755)
monkeypatch.setenv("PATH", str(wrapper) + os.pathsep + os.environ["PATH"])

result = subprocess.run(["git", "--version"], check=True, capture_output=True, text=True, timeout=30)

assert result.stdout == expected
Loading