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
15 changes: 13 additions & 2 deletions gptdiff/applydiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,19 @@ def apply_patch_to_file(file_path, patch):
# Addition line: add to new_lines.
new_lines.append(pline[1:] + "\n")
else:
print("Unexpected line in hunk:", pline)
return False
# Some diffs (especially LLM-generated) omit the leading space on
# context lines. Treat bare lines as context when they match the
# original file to make patch application more forgiving.
expected = pline
if current_index >= len(original_lines):
print("Context line expected but file ended")
return False
orig_line = original_lines[current_index].rstrip("\n")
if orig_line != expected:
print("Context line mismatch. Expected:", expected, "Got:", orig_line)
return False
new_lines.append(original_lines[current_index])
current_index += 1
i += 1
else:
# Skip non-hunk header lines.
Expand Down
24 changes: 24 additions & 0 deletions tests/test_applydiff_edgecases.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@ def test_diff_with_whitespace_changes(tmp_project_dir):
assert "line2 " in content, "Whitespace change should be reflected in the file"


def test_diff_without_context_prefixes(tmp_project_dir):
"""
Diffs generated by LLMs sometimes omit the leading space on context lines.
Ensure we still treat those lines as context when they match the file.
"""
file = tmp_project_dir / "example.txt"
file.write_text("line1\nline2\nline3\n")
diff_text = (
"diff --git a/example.txt b/example.txt\n"
"--- a/example.txt\n"
"+++ a/example.txt\n"
"@@ -1,3 +1,3 @@\n"
"line1\n"
"-line2\n"
"+line2 updated\n"
"line3\n"
)

result = apply_diff(str(tmp_project_dir), diff_text)

assert result is True, "Diff without context prefixes should still apply"
assert file.read_text() == "line1\nline2 updated\nline3\n"


def test_diff_file_deletion_edge(tmp_project_dir):
"""
Test deletion diff for a file with minimal content.
Expand Down