|
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)}
|