Compare commits

...

1 Commits

Author SHA1 Message Date
openhands fc004f79e6 Fix Makefile tab handling in patch application
- Add special case to preserve tabs in Makefiles
- Disable whitespace normalization for Makefiles
- Add tests to verify tab preservation and whitespace handling
2025-03-24 22:29:16 +00:00
2 changed files with 75 additions and 5 deletions
+14 -5
View File
@@ -97,17 +97,26 @@ def apply_diff(
hunk=hunk,
)
if lines[old - 1] != line:
# Try to normalize whitespace by replacing multiple spaces with a single space
# This helps with patches that have different indentation levels
normalized_line = ' '.join(line.split())
normalized_source = ' '.join(lines[old - 1].split())
if normalized_line != normalized_source:
# For Makefiles, we need to preserve tabs since they are significant
if diff.header.new_path and diff.header.new_path.endswith('Makefile'):
raise HunkApplyException(
'context line {n}, "{line}" does not match "{sl}"'.format(
n=old, line=line, sl=lines[old - 1]
),
hunk=hunk,
)
else:
# Try to normalize whitespace by replacing multiple spaces with a single space
# This helps with patches that have different indentation levels
normalized_line = ' '.join(line.split())
normalized_source = ' '.join(lines[old - 1].split())
if normalized_line != normalized_source:
raise HunkApplyException(
'context line {n}, "{line}" does not match "{sl}"'.format(
n=old, line=line, sl=lines[old - 1]
),
hunk=hunk,
)
# for calculating the old line
r = 0
+61
View File
@@ -0,0 +1,61 @@
from openhands.resolver.patching.apply import apply_diff
from openhands.resolver.patching.patch import parse_patch
def test_makefile_parsing():
"""Test that we can correctly parse a Makefile with tabs."""
# Create a simple Makefile with a tab
makefile_content = "all:\n\techo hello\n"
lines = makefile_content.splitlines()
assert lines == ['all:', '\techo hello']
# Create a patch that adds a new target
patch_text = """diff --git a/Makefile b/Makefile
index 1234567..89abcdef 100
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,4 @@
all:
- echo hello
+ echo hello
+test:
+ echo test"""
patch = next(parse_patch(patch_text))
new_content = apply_diff(patch, makefile_content)
# Verify that tabs are preserved in the output
expected = [
'all:',
'\techo hello',
'test:',
'\techo test',
]
assert new_content == expected
def test_makefile_whitespace_normalization():
"""Test that whitespace normalization is disabled for Makefiles."""
# Create a simple Makefile with a tab
makefile_content = "all:\n\techo hello\n"
lines = makefile_content.splitlines()
assert lines == ['all:', '\techo hello']
# Create a patch that has spaces instead of tabs
patch_text = """diff --git a/Makefile b/Makefile
index 1234567..89abcdef 100
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,4 @@
all:
- echo hello
+ echo hello
+test:
+ echo test"""
patch = next(parse_patch(patch_text))
try:
new_content = apply_diff(patch, makefile_content)
assert False, "Expected HunkApplyException due to tab vs space mismatch"
except Exception as e:
assert "does not match" in str(e)