import difflib
import os
import subprocess
import tempfile
from ..ui.diff_display import display_diff, get_diff_stats
def apply_patch(filepath, patch_content, db_conn=None):
try:
path = os.path.expanduser(filepath)
if db_conn:
from pr.tools.database import db_get
read_status = db_get("read:" + path, db_conn)
if read_status.get("status") != "success" or read_status.get("value") != "true":
return {
"status": "error",
"error": "File must be read before writing. Please read the file first.",
}
# Write patch to temp file
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".patch") as f:
f.write(patch_content)
patch_file = f.name
# Run patch command
result = subprocess.run(
["patch", path, patch_file],
capture_output=True,
text=True,
cwd=os.path.dirname(path),
)
os.unlink(patch_file)
if result.returncode == 0:
return {"status": "success", "output": result.stdout.strip()}
else:
return {"status": "error", "error": result.stderr.strip()}
except Exception as e:
return {"status": "error", "error": str(e)}
def create_diff(
file1, file2, fromfile="file1", tofile="file2", visual=False, format_type="unified"
):
try:
path1 = os.path.expanduser(file1)
path2 = os.path.expanduser(file2)
with open(path1) as f1, open(path2) as f2:
content1 = f1.read()
content2 = f2.read()
if visual:
visual_diff = display_diff(content1, content2, fromfile, format_type)
stats = get_diff_stats(content1, content2)
lines1 = content1.splitlines(keepends=True)
lines2 = content2.splitlines(keepends=True)
plain_diff = list(
difflib.unified_diff(lines1, lines2, fromfile=fromfile, tofile=tofile)
)
return {
"status": "success",
"diff": "".join(plain_diff),
"visual_diff": visual_diff,
"stats": stats,
}
else:
lines1 = content1.splitlines(keepends=True)
lines2 = content2.splitlines(keepends=True)
diff = list(difflib.unified_diff(lines1, lines2, fromfile=fromfile, tofile=tofile))
return {"status": "success", "diff": "".join(diff)}
except Exception as e:
return {"status": "error", "error": str(e)}
def display_file_diff(filepath1, filepath2, format_type="unified", context_lines=3):
try:
path1 = os.path.expanduser(filepath1)
path2 = os.path.expanduser(filepath2)
with open(path1) as f1:
old_content = f1.read()
with open(path2) as f2:
new_content = f2.read()
visual_diff = display_diff(old_content, new_content, filepath1, format_type)
stats = get_diff_stats(old_content, new_content)
return {"status": "success", "visual_diff": visual_diff, "stats": stats}
except Exception as e:
return {"status": "error", "error": str(e)}
def display_content_diff(old_content, new_content, filename="file", format_type="unified"):
try:
visual_diff = display_diff(old_content, new_content, filename, format_type)
stats = get_diff_stats(old_content, new_content)
return {"status": "success", "visual_diff": visual_diff, "stats": stats}
except Exception as e:
return {"status": "error", "error": str(e)}