Popular Posts
android.intent.action.SCREEN_ON & android.intent.action.SCREEN_OFF First, I've tried create a receiver to receive screen on/off and register receiver on AndroidManifest.xml like below, but unfortunately ... Memo: Debounce Task To prevent multi-execution from caller in short time, use debounce for single execution. var debounce = function (func, threshold, execAsap... Multiple line of text limit With Sharepoint Designer, edit the page of list view. Add xsl template as below to override original template. Source template could be foun...
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: