Popular Posts
ADD ... THEN ... UNTIL ... data: begin of SERIES, N1 type I value 10, N2 type I value 20, N3 type I value 30, N4 type I value 40, ... Remove file not in list Append soap header into axis When axis generate classese of web service, it won't include the request of soap header. Here is a way to append soap header manually i...
Stats
Showing posts with label python. Show all posts
Showing posts with label python. Show all posts
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: