"""代码差异对比命令:diff。""" from __future__ import annotations import argparse import difflib import logging import os from sapcli.client import ADTClient from sapcli.types import get_type_config, parse_object_name logger = logging.getLogger("sapcli.commands.diff_cmd") def cmd_diff(args: argparse.Namespace, client: ADTClient) -> None: """本地 vs SAP 代码差异对比。""" name: str = args.name obj_type: str = args.type local_path: str | None = getattr(args, "path", None) parsed = parse_object_name(name, obj_type) type_label = get_type_config(obj_type).label if parsed.src_uri is None: print(f"\n ✗ {type_label}没有源代码,不支持 diff 操作") return print("=" * 60) print(" SAP ADT 代码差异对比") print("=" * 60) print(f" 对象名称: {parsed.display_name}") print(f" 对象类型: {type_label}") # 读取本地文件 if local_path is None: # 尝试自动推断文件路径 local_path = f"{parsed.file_base}.abap" if not os.path.isfile(local_path): print(f"\n ✗ 本地文件不存在: {local_path}") return with open(local_path, "r", encoding="utf-8") as f: local_source = f.read() local_lines = local_source.splitlines(keepends=True) print(f" 本地文件: {local_path} ({len(local_lines)} 行)") # 读取 SAP 端源码 print(f"\n → 正在读取 SAP 端源码...") try: sap_source = client.read_source_for_diff(name, obj_type) except Exception as e: print(f" ✗ 读取 SAP 源码失败: {e}") return sap_source = sap_source.replace("\r\n", "\n").replace("\r", "\n") sap_lines = sap_source.splitlines(keepends=True) print(f" ✓ SAP 源码读取成功 ({len(sap_lines)} 行)") # 生成 unified diff diff_lines = list(difflib.unified_diff( sap_lines, local_lines, fromfile=f"SAP:{parsed.display_name}", tofile=f"本地:{os.path.basename(local_path)}", lineterm="", )) if not diff_lines: print(f"\n ✓ 本地文件与 SAP 端完全一致,无差异") return print(f"\n {'─' * 60}") print(f" 差异摘要:") added = sum(1 for l in diff_lines if l.startswith("+") and not l.startswith("+++")) removed = sum(1 for l in diff_lines if l.startswith("-") and not l.startswith("---")) print(f" 新增行: {added} | 删除行: {removed}") print(f" {'─' * 60}\n") # 输出 diff for line in diff_lines: if line.startswith("+") and not line.startswith("+++"): print(f" \033[32m{line}\033[0m") elif line.startswith("-") and not line.startswith("---"): print(f" \033[31m{line}\033[0m") elif line.startswith("@@"): print(f" \033[36m{line}\033[0m") else: print(f" {line}")