Popular Posts
Enable SSL connection for Jsoup import org.jsoup.Connection; import org.jsoup.Jsoup; import javax.net.ssl.*; import java.io.IOException; import java.security.KeyManagement... Word break tag : <wbr/> (HTML5) The  HTML  <wbr>  tag  is  used  defines  a  potential  line  break  point  if  needed.  This  stands  for  Word  BReak. This  is  u... Build an OpenVPN server on android device Preparation An android device, in this case, Sony xperia Z is used Root permission required Linux Deploy for deploy i...
Stats
Generate subversion diff report using python

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: