chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from opensquilla.tools.source_diff_candidates import (
|
||||
MAX_PATCH_CHARS,
|
||||
capture_source_diff_candidate,
|
||||
latest_recoverable_source_candidate,
|
||||
mark_source_diff_candidates_lost,
|
||||
)
|
||||
from opensquilla.tools.types import ToolContext
|
||||
|
||||
|
||||
def _run_git(workspace: Path, *args: str) -> None:
|
||||
subprocess.run(
|
||||
["git", *args],
|
||||
cwd=workspace,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
|
||||
|
||||
def _init_git_workspace(workspace: Path) -> Path:
|
||||
(workspace / "src").mkdir()
|
||||
target = workspace / "src" / "a.py"
|
||||
target.write_text("old\n", encoding="utf-8")
|
||||
_run_git(workspace, "init")
|
||||
_run_git(workspace, "config", "user.email", "test@example.com")
|
||||
_run_git(workspace, "config", "user.name", "Test User")
|
||||
_run_git(workspace, "add", ".")
|
||||
_run_git(workspace, "commit", "-m", "init")
|
||||
return target
|
||||
|
||||
|
||||
def test_capture_source_candidate_records_patch(tmp_path: Path) -> None:
|
||||
target = _init_git_workspace(tmp_path)
|
||||
target.write_text("new\n", encoding="utf-8")
|
||||
events: list[dict[str, object]] = []
|
||||
|
||||
ctx = ToolContext(workspace_dir=str(tmp_path), on_runtime_event=events.append)
|
||||
candidate = capture_source_diff_candidate(
|
||||
ctx=ctx,
|
||||
relative_path="src/a.py",
|
||||
workspace_epoch=1,
|
||||
receipt_id="receipt-1",
|
||||
tool_name="edit_source",
|
||||
)
|
||||
|
||||
assert candidate is not None
|
||||
assert candidate["candidate_id"].startswith("srcdiff-")
|
||||
assert candidate["paths"] == ["src/a.py"]
|
||||
assert "-old" in candidate["patch"]
|
||||
assert "+new" in candidate["patch"]
|
||||
assert latest_recoverable_source_candidate(ctx) == candidate
|
||||
assert events[-1]["name"] == "source_diff_candidate.captured"
|
||||
|
||||
|
||||
def test_capture_source_candidate_skips_when_mode_off(tmp_path: Path) -> None:
|
||||
target = _init_git_workspace(tmp_path)
|
||||
target.write_text("new\n", encoding="utf-8")
|
||||
events: list[dict[str, object]] = []
|
||||
|
||||
ctx = ToolContext(
|
||||
workspace_dir=str(tmp_path),
|
||||
source_diff_candidate_mode="off",
|
||||
on_runtime_event=events.append,
|
||||
)
|
||||
candidate = capture_source_diff_candidate(
|
||||
ctx=ctx,
|
||||
relative_path="src/a.py",
|
||||
workspace_epoch=1,
|
||||
receipt_id="receipt-1",
|
||||
tool_name="edit_source",
|
||||
)
|
||||
|
||||
assert candidate is None
|
||||
assert ctx.source_diff_candidates == []
|
||||
assert events == []
|
||||
|
||||
|
||||
def test_capture_source_candidate_skips_non_git_workspace(tmp_path: Path) -> None:
|
||||
target = tmp_path / "src" / "a.py"
|
||||
target.parent.mkdir()
|
||||
target.write_text("new\n", encoding="utf-8")
|
||||
events: list[dict[str, object]] = []
|
||||
|
||||
ctx = ToolContext(workspace_dir=str(tmp_path), on_runtime_event=events.append)
|
||||
candidate = capture_source_diff_candidate(
|
||||
ctx=ctx,
|
||||
relative_path="src/a.py",
|
||||
workspace_epoch=1,
|
||||
receipt_id="receipt-1",
|
||||
tool_name="edit_source",
|
||||
)
|
||||
|
||||
assert candidate is None
|
||||
assert events[-1]["name"] == "source_diff_candidate.capture_skipped"
|
||||
assert events[-1]["reason"] == "git_diff_failed"
|
||||
|
||||
|
||||
def test_capture_source_candidate_skips_oversized_patch(tmp_path: Path) -> None:
|
||||
target = _init_git_workspace(tmp_path)
|
||||
target.write_text("x" * (MAX_PATCH_CHARS + 1), encoding="utf-8")
|
||||
events: list[dict[str, object]] = []
|
||||
|
||||
ctx = ToolContext(workspace_dir=str(tmp_path), on_runtime_event=events.append)
|
||||
candidate = capture_source_diff_candidate(
|
||||
ctx=ctx,
|
||||
relative_path="src/a.py",
|
||||
workspace_epoch=1,
|
||||
receipt_id="receipt-1",
|
||||
tool_name="edit_source",
|
||||
)
|
||||
|
||||
assert candidate is None
|
||||
assert ctx.source_diff_candidates == []
|
||||
assert events[-1]["reason"] == "patch_too_large"
|
||||
|
||||
|
||||
def test_mark_source_diff_candidates_lost_updates_matching_candidates() -> None:
|
||||
events: list[dict[str, object]] = []
|
||||
ctx = ToolContext(on_runtime_event=events.append)
|
||||
ctx.source_diff_candidates.extend(
|
||||
[
|
||||
{
|
||||
"candidate_id": "srcdiff-1",
|
||||
"paths": ["src/a.py"],
|
||||
"patch": "diff --git a/src/a.py b/src/a.py\n",
|
||||
"lost": False,
|
||||
"restored": False,
|
||||
},
|
||||
{
|
||||
"candidate_id": "srcdiff-2",
|
||||
"paths": ["src/b.py"],
|
||||
"patch": "diff --git a/src/b.py b/src/b.py\n",
|
||||
"lost": False,
|
||||
"restored": False,
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
marked = mark_source_diff_candidates_lost(
|
||||
ctx=ctx,
|
||||
paths=["src/a.py"],
|
||||
reason="source_diff_revert_observed",
|
||||
command="git checkout -- src/a.py",
|
||||
)
|
||||
|
||||
assert [item["candidate_id"] for item in marked] == ["srcdiff-1"]
|
||||
assert ctx.source_diff_candidates[0]["lost"] is True
|
||||
assert ctx.source_diff_candidates[0]["lost_reason"] == "source_diff_revert_observed"
|
||||
assert ctx.source_diff_candidates[1]["lost"] is False
|
||||
assert events[-1]["name"] == "source_diff_candidate.marked_lost"
|
||||
Reference in New Issue
Block a user