bash:
svn --diff-cmd "python" --extensions "diff_to_html.py" diff -r 596:671
diff_to_html.py
import sys import difflib import os import argparse FOLDER_MODIFY = 'modify' FOLDER_ADD = 'add' FOLDER_DELETE = 'delete' # 解析參數 parser = argparse.ArgumentParser() parser.add_argument('-u', action='store_true') parser.add_argument('-L', action='store_true') parser.add_argument('-r', '--report', default='report') parser.add_argument('-w', '--white-list', nargs='+', default=['.cs', '.csproj', '.config', '.xml', '.sln']) parser.add_argument('revfrom') parser.add_argument('revto') parser.add_argument('filefrom') parser.add_argument('fileto') args = parser.parse_args() from_file = args.revfrom to_file = args.revto from_file_path = args.filefrom to_file_path = args.fileto output_folder = args.report white_list = args.white_list # inject inject_script = """ <script> document.body.onload = function () { readableChange(); } function readableChange() { var className = 'diff_chg'; var lines = getChangedRows(className); // 頭尾應為文字內容 lines.forEach(function (item) { var headerText = item.firstChild.data; var tailText = item.lastChild.data; var fullText = Array.prototype.map.call(item.childNodes, function (child) { return child.nodeType == '3' ? child.data : child.innerText; }); if (headerText !== undefined) { fullText.shift(); } if (tailText !== undefined) { fullText.pop(); } var i = 10; while (item.lastChild) { item.removeChild(item.lastChild); } item.appendChild(document.createTextNode(headerText || '')); item.appendChild(createMark(className, fullText)) item.appendChild(document.createTextNode(tailText || '')); }) } function createMark(className, text) { var mark = document.createElement('span'); mark.classList.add(className); mark.appendChild(document.createTextNode(text.join(''))); return mark; } function getChangedRows(className) { var changedLines = Array.prototype.map.call(document.querySelectorAll('.' + className), function (element) { return element.parentElement; }); changedLines = changedLines.filter(function (element) { return element.tagName == 'TD'; }); var lines = []; for (var i = 0; i < changedLines.length; i++) { var line = changedLines[i]; if (!lines.find(function (item) { return item == line; })) { lines.push(line); } } return lines; } </script> """ inject_styles = """ <style> * { font-size: 0.9rem !important; } </style> """ def readlines(path): """ 讀取檔案內容 """ content = None try: with open(file=path, mode='rt', encoding='utf-8') as f: content = [l for l in f.readlines()] except: try: with open(file=path, mode='rt', encoding='ms950') as f: content = [l for l in f.readlines()] except: print('讀取 {} 失敗'.format(path)) return content def execute(): """ 比對檔案產出 HTML """ print('讀取檔案 {}'.format(to_file_path)) to_file_content = readlines(to_file_path) print('讀取檔案 {}'.format(from_file_path)) from_file_content = readlines(from_file_path) if to_file_content is None or from_file_path is None: return html = difflib.HtmlDiff().make_file( from_file_content, to_file_content, from_file, to_file, context=True) html = html.replace('</head>', inject_styles + '</head>') html = html.replace('</body>', inject_script + '</body>') output_file = '{}.html'.format(to_file[0: to_file.find('\t')]) output_file = output_file.replace('/', '_') output_file = output_file.replace('\\', '_') if len(to_file_content) == 0: output_file = os.path.join(output_folder, FOLDER_DELETE, output_file) if not os.path.exists(os.path.join(output_folder, FOLDER_DELETE)): os.makedirs(os.path.join(output_folder, FOLDER_DELETE)) elif len(from_file_content) == 0: output_file = os.path.join(output_folder, FOLDER_ADD, output_file) if not os.path.exists(os.path.join(output_folder, FOLDER_ADD)): os.makedirs(os.path.join(output_folder, FOLDER_ADD)) else: output_file = os.path.join(output_folder, FOLDER_MODIFY, output_file) if not os.path.exists(os.path.join(output_folder, FOLDER_MODIFY)): os.makedirs(os.path.join(output_folder, FOLDER_MODIFY)) print('寫入檔案 {}'.format(output_file)) with open(file=output_file, mode='wt', encoding='utf-8') as f: f.write(html) if len([ext for ext in white_list if to_file[0: to_file.find('\t')].lower().endswith(ext.lower())]) > 0: execute() else: print('不處理 {} 的檔案比對。'.format(to_file[0: to_file.find('\t')]))
output file: