chore: archive previous Aider worker
This commit is contained in:
239
old_2026-08-31/tests/test_git.py
Normal file
239
old_2026-08-31/tests/test_git.py
Normal file
@@ -0,0 +1,239 @@
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock
|
||||
|
||||
from test_config import settings
|
||||
|
||||
from lai_automation.git import GitWorkspace
|
||||
|
||||
|
||||
def test_prepare_uses_temporary_authentication_for_private_clone(tmp_path, monkeypatch) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path, gitea_token="token"), 10)
|
||||
calls = []
|
||||
|
||||
def run(command, **kwargs):
|
||||
calls.append((command, kwargs))
|
||||
if command[1] == "clone":
|
||||
askpass = Path(kwargs["env"]["GIT_ASKPASS"])
|
||||
assert askpass.is_file()
|
||||
assert Path(kwargs["env"]["GIT_BOT_USER_FILE"]).read_text() == "bot"
|
||||
assert Path(kwargs["env"]["GIT_BOT_TOKEN_FILE"]).read_text() == "token"
|
||||
workspace.path.mkdir()
|
||||
return subprocess.CompletedProcess(command, 0, "", "")
|
||||
|
||||
monkeypatch.setattr("lai_automation.git.subprocess.run", run)
|
||||
|
||||
workspace.prepare()
|
||||
|
||||
clone_command, clone_options = calls[0]
|
||||
assert clone_command[:2] == ["git", "clone"]
|
||||
assert "token" not in " ".join(clone_command)
|
||||
assert clone_options["cwd"] == tmp_path
|
||||
assert not tuple(tmp_path.glob(".lai-git-auth-*"))
|
||||
|
||||
|
||||
def test_prepare_surfaces_clone_stderr_without_credentials(tmp_path, monkeypatch) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path, gitea_token="token"), 11)
|
||||
|
||||
def run(command, **kwargs):
|
||||
raise subprocess.CalledProcessError(
|
||||
128,
|
||||
command,
|
||||
output="",
|
||||
stderr="fatal: upstream returned 403",
|
||||
)
|
||||
|
||||
monkeypatch.setattr("lai_automation.git.subprocess.run", run)
|
||||
|
||||
try:
|
||||
workspace.prepare()
|
||||
except RuntimeError as exception:
|
||||
message = str(exception)
|
||||
else:
|
||||
raise AssertionError("Expected clone failure")
|
||||
|
||||
assert "Source repository clone failed" in message
|
||||
assert "upstream returned 403" in message
|
||||
assert "token" not in message
|
||||
assert not tuple(tmp_path.glob(".lai-git-auth-*"))
|
||||
|
||||
|
||||
def test_test_command_does_not_interpret_shell_metacharacters(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 1)
|
||||
workspace.path.mkdir()
|
||||
|
||||
result = workspace.run("printf safe ; touch injected", check=False)
|
||||
|
||||
assert result.stdout == "safe"
|
||||
assert not (workspace.path / "injected").exists()
|
||||
|
||||
|
||||
def test_extra_environment_is_passed_without_privilege_drop(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 6)
|
||||
workspace.path.mkdir()
|
||||
|
||||
result = workspace.run_args(
|
||||
[sys.executable, "-c", "import os; print(os.environ['SAFE_TEST_VALUE'])"],
|
||||
extra_environment={"SAFE_TEST_VALUE": "available"},
|
||||
)
|
||||
|
||||
assert result.stdout.strip() == "available"
|
||||
|
||||
|
||||
def test_coder_commands_use_native_process_identity(tmp_path, monkeypatch) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 9)
|
||||
workspace.path.mkdir()
|
||||
captured = {}
|
||||
|
||||
def run(command, **kwargs):
|
||||
captured.update(kwargs)
|
||||
return subprocess.CompletedProcess(command, 0, "ok", "")
|
||||
|
||||
monkeypatch.setattr("lai_automation.git.subprocess.run", run)
|
||||
monkeypatch.setattr(
|
||||
"lai_automation.git.pwd.getpwnam",
|
||||
lambda _: Mock(pw_dir="/home/coder", pw_uid=10001, pw_gid=10001),
|
||||
)
|
||||
|
||||
workspace.run_args(["php", "-v"], username="coder")
|
||||
|
||||
assert captured["user"] == 10001
|
||||
assert captured["group"] == 10001
|
||||
assert captured["extra_groups"] == ()
|
||||
assert "preexec_fn" not in captured
|
||||
|
||||
|
||||
def test_summary_includes_untracked_files(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 2)
|
||||
workspace.path.mkdir()
|
||||
subprocess.run(["git", "init"], cwd=workspace.path, check=True, capture_output=True)
|
||||
(workspace.path / "new.php").write_text("<?php\n")
|
||||
|
||||
summary = workspace.summary()
|
||||
|
||||
assert summary.files == ("new.php",)
|
||||
assert summary.added_lines == 1
|
||||
|
||||
|
||||
def test_summary_includes_checkpoint_staged_files(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 7)
|
||||
workspace.path.mkdir()
|
||||
subprocess.run(["git", "init"], cwd=workspace.path, check=True, capture_output=True)
|
||||
tracked = workspace.path / "config.php"
|
||||
tracked.write_text("<?php\nreturn [];\n")
|
||||
subprocess.run(["git", "add", "."], cwd=workspace.path, check=True)
|
||||
subprocess.run(
|
||||
["git", "-c", "user.email=test@example.invalid", "-c", "user.name=Test",
|
||||
"commit", "-m", "base"],
|
||||
cwd=workspace.path,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
tracked.write_text("<?php\nreturn ['fixed'];\n")
|
||||
|
||||
workspace.checkpoint()
|
||||
summary = workspace.summary()
|
||||
|
||||
assert summary.files == ("config.php",)
|
||||
assert summary.added_lines == 1
|
||||
assert summary.deleted_lines == 1
|
||||
|
||||
|
||||
def test_discard_changes_restores_clean_disposable_workspace(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 3)
|
||||
workspace.path.mkdir()
|
||||
subprocess.run(["git", "init"], cwd=workspace.path, check=True, capture_output=True)
|
||||
subprocess.run(
|
||||
["git", "config", "user.email", "test@example.invalid"],
|
||||
cwd=workspace.path,
|
||||
check=True,
|
||||
)
|
||||
subprocess.run(
|
||||
["git", "config", "user.name", "Test"],
|
||||
cwd=workspace.path,
|
||||
check=True,
|
||||
)
|
||||
tracked = workspace.path / "tracked.php"
|
||||
tracked.write_text("<?php\nreturn [];\n")
|
||||
subprocess.run(["git", "add", "."], cwd=workspace.path, check=True)
|
||||
subprocess.run(["git", "commit", "-m", "base"], cwd=workspace.path, check=True, capture_output=True)
|
||||
tracked.write_text("<?php\ninvalid\n")
|
||||
untracked = workspace.path / "extra.php"
|
||||
untracked.write_text("<?php\n")
|
||||
|
||||
workspace.discard_changes()
|
||||
|
||||
assert tracked.read_text() == "<?php\nreturn [];\n"
|
||||
assert not untracked.exists()
|
||||
|
||||
|
||||
def test_checkpoint_restores_last_valid_changes(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 4)
|
||||
workspace.path.mkdir()
|
||||
subprocess.run(["git", "init"], cwd=workspace.path, check=True, capture_output=True)
|
||||
subprocess.run(
|
||||
["git", "config", "user.email", "test@example.invalid"],
|
||||
cwd=workspace.path,
|
||||
check=True,
|
||||
)
|
||||
subprocess.run(
|
||||
["git", "config", "user.name", "Test"],
|
||||
cwd=workspace.path,
|
||||
check=True,
|
||||
)
|
||||
tracked = workspace.path / "config.php"
|
||||
tracked.write_text("<?php\nreturn [];\n")
|
||||
subprocess.run(["git", "add", "."], cwd=workspace.path, check=True)
|
||||
subprocess.run(["git", "commit", "-m", "base"], cwd=workspace.path, check=True, capture_output=True)
|
||||
tracked.write_text("<?php\nreturn ['valid'];\n")
|
||||
added = workspace.path / "test.php"
|
||||
added.write_text("<?php\n")
|
||||
checkpoint = workspace.checkpoint()
|
||||
tracked.write_text("<?php\nreturn [broken;\n")
|
||||
|
||||
workspace.restore_checkpoint(checkpoint)
|
||||
|
||||
assert tracked.read_text() == "<?php\nreturn ['valid'];\n"
|
||||
assert added.exists()
|
||||
|
||||
|
||||
def test_diff_returns_discarded_patch_excerpt(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 5)
|
||||
workspace.path.mkdir()
|
||||
subprocess.run(["git", "init"], cwd=workspace.path, check=True, capture_output=True)
|
||||
tracked = workspace.path / "service.php"
|
||||
tracked.write_text("<?php\nreturn 'old';\n")
|
||||
subprocess.run(["git", "add", "."], cwd=workspace.path, check=True)
|
||||
subprocess.run(
|
||||
["git", "-c", "user.email=test@example.invalid", "-c", "user.name=Test", "commit", "-m", "base"],
|
||||
cwd=workspace.path,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
tracked.write_text("<?php\nreturn 'new';\n")
|
||||
|
||||
patch = workspace.diff()
|
||||
|
||||
assert "-return 'old';" in patch
|
||||
assert "+return 'new';" in patch
|
||||
|
||||
|
||||
def test_head_file_reads_original_tracked_content(tmp_path) -> None:
|
||||
workspace = GitWorkspace(settings(workspace_root=tmp_path), 8)
|
||||
workspace.path.mkdir()
|
||||
subprocess.run(["git", "init"], cwd=workspace.path, check=True, capture_output=True)
|
||||
tracked = workspace.path / "config.php"
|
||||
tracked.write_text("<?php\nreturn 'original';\n")
|
||||
subprocess.run(["git", "add", "."], cwd=workspace.path, check=True)
|
||||
subprocess.run(
|
||||
["git", "-c", "user.email=test@example.invalid", "-c", "user.name=Test",
|
||||
"commit", "-m", "base"],
|
||||
cwd=workspace.path,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
tracked.write_text("<?php\nreturn 'candidate';\n")
|
||||
|
||||
assert workspace.head_file("config.php") == "<?php\nreturn 'original';\n"
|
||||
assert workspace.head_file("missing.php") is None
|
||||
Reference in New Issue
Block a user