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: