Fix patching
This commit is contained in:
+39
-18
@@ -11,6 +11,7 @@ import os
|
||||
import sys
|
||||
import re
|
||||
import shutil
|
||||
import difflib
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Optional, Any
|
||||
import argparse
|
||||
@@ -204,18 +205,18 @@ class GitPatchHandler:
|
||||
}
|
||||
|
||||
def _try_fuzzy_apply(self, patch_file: str, target_dir: str, previous_result: subprocess.CompletedProcess) -> Dict[str, Any]:
|
||||
"""Try applying patch with fuzzy matching"""
|
||||
self._log("Attempting fuzzy patch application")
|
||||
"""Try applying patch with --reject to apply what fits, then check for leftover .rej files"""
|
||||
self._log("Attempting fuzzy patch application with --reject")
|
||||
try:
|
||||
cmd = [
|
||||
'git', 'apply',
|
||||
'--3way',
|
||||
'--allow-overlap',
|
||||
'--verbose',
|
||||
'--reject', # Apply parts that work, reject others
|
||||
'--reject', # Apply hunks that work, write .rej for those that don't
|
||||
str(patch_file)
|
||||
]
|
||||
|
||||
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
cwd=target_dir,
|
||||
@@ -223,15 +224,34 @@ class GitPatchHandler:
|
||||
text=True,
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if result.returncode == 0 or 'applied' in result.stdout.lower():
|
||||
|
||||
# Check for leftover .rej files — these mean hunks were skipped
|
||||
rej_files = list(Path(target_dir).rglob('*.rej'))
|
||||
if rej_files:
|
||||
rej_names = [str(r.relative_to(target_dir)) for r in rej_files]
|
||||
self._log(f"Found {len(rej_files)} reject file(s): {rej_names}")
|
||||
# Clean up .rej files so they don't pollute the tree
|
||||
for rej in rej_files:
|
||||
try:
|
||||
rej.unlink()
|
||||
except OSError:
|
||||
pass
|
||||
return {
|
||||
'success': True,
|
||||
'message': 'Patch applied with rejects',
|
||||
'success': False,
|
||||
'message': f'Patch partially applied — {len(rej_files)} hunk(s) rejected',
|
||||
'output': result.stdout,
|
||||
'error': result.stderr,
|
||||
'method': 'git-fuzzy',
|
||||
'had_rejects': 'reject' in result.stdout.lower()
|
||||
'rejected_files': rej_names
|
||||
}
|
||||
|
||||
if result.returncode == 0:
|
||||
return {
|
||||
'success': True,
|
||||
'message': 'Patch applied cleanly (fuzzy)',
|
||||
'output': result.stdout,
|
||||
'error': result.stderr,
|
||||
'method': 'git-fuzzy'
|
||||
}
|
||||
else:
|
||||
return {
|
||||
@@ -242,7 +262,7 @@ class GitPatchHandler:
|
||||
'error': result.stderr,
|
||||
'method': 'git-fuzzy'
|
||||
}
|
||||
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
'success': False,
|
||||
@@ -357,11 +377,15 @@ class GitPatchHandler:
|
||||
files = []
|
||||
for line in patch_content.split('\n'):
|
||||
if line.startswith('--- ') or line.startswith('+++ '):
|
||||
file_path = line.split(' ')[1]
|
||||
if file_path != '/dev/null' and not file_path.startswith('a/') and not file_path.startswith('b/'):
|
||||
# Clean up git-style prefixes
|
||||
clean_path = re.sub(r'^(a|b)/', '', file_path)
|
||||
files.append(clean_path)
|
||||
parts = line.split(' ', 1)
|
||||
if len(parts) < 2:
|
||||
continue
|
||||
file_path = parts[1].split('\t')[0].strip() # handle timestamps after tab
|
||||
if file_path == '/dev/null':
|
||||
continue
|
||||
# Strip git-style a/ or b/ prefixes (standard in git format-patch output)
|
||||
clean_path = re.sub(r'^[ab]/', '', file_path)
|
||||
files.append(clean_path)
|
||||
return list(set(files))
|
||||
|
||||
def _count_lines_changed(self, patch_content: str) -> int:
|
||||
@@ -606,8 +630,5 @@ def print_patch_results(result: Dict[str, Any]) -> None:
|
||||
print(f" [ROLLED BACK]")
|
||||
|
||||
|
||||
# Add difflib for the create_patch method
|
||||
import difflib
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user