Popular Posts
javax.net.ssl.SSLHandshakeException: Connection closed by peer in Android 5.0 Lollipop Recently, there is a error occurs when access website via ssl connection like below although it worked fine several days ago. // Enable SSL... 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... set/remove cookie using applet jdk/jre 1.4 later, the library is included in plugin.jar file. import java.applet.Applet; import java.util.ArrayList; import java.util.Date;...
Stats
Generate subversion diff report using python

bash:

  1. svn --diff-cmd "python" --extensions "diff_to_html.py" diff -r 596:671

diff_to_html.py

  1. import sys
  2. import difflib
  3. import os
  4. import argparse
  5.  
  6. FOLDER_MODIFY = 'modify'
  7. FOLDER_ADD = 'add'
  8. FOLDER_DELETE = 'delete'
  9.  
  10. # 解析參數
  11. parser = argparse.ArgumentParser()
  12. parser.add_argument('-u', action='store_true')
  13. parser.add_argument('-L', action='store_true')
  14. parser.add_argument('-r', '--report', default='report')
  15. parser.add_argument('-w', '--white-list',
  16.                     nargs='+',
  17.                     default=['.cs', '.csproj', '.config', '.xml', '.sln'])
  18. parser.add_argument('revfrom')
  19. parser.add_argument('revto')
  20. parser.add_argument('filefrom')
  21. parser.add_argument('fileto')
  22. args = parser.parse_args()
  23.  
  24. from_file = args.revfrom
  25. to_file = args.revto
  26. from_file_path = args.filefrom
  27. to_file_path = args.fileto
  28.  
  29. output_folder = args.report
  30. white_list = args.white_list
  31.  
  32. # inject
  33. inject_script = """
  34.     <script>
  35.         document.body.onload = function () {
  36.             readableChange();
  37.         }
  38.  
  39.         function readableChange() {
  40.             var className = 'diff_chg';
  41.             var lines = getChangedRows(className);
  42.  
  43.             // 頭尾應為文字內容
  44.             lines.forEach(function (item) {
  45.                 var headerText = item.firstChild.data;
  46.                 var tailText = item.lastChild.data;
  47.                 var fullText = Array.prototype.map.call(item.childNodes, function (child) {
  48.                     return child.nodeType == '3' ? child.data : child.innerText;
  49.                 });
  50.  
  51.                 if (headerText !== undefined) {
  52.                     fullText.shift();
  53.                 }
  54.                 if (tailText !== undefined) {
  55.                     fullText.pop();
  56.                 }
  57.  
  58.                 var i = 10;
  59.                 while (item.lastChild) {
  60.                     item.removeChild(item.lastChild);
  61.                 }
  62.  
  63.                 item.appendChild(document.createTextNode(headerText || ''));
  64.                 item.appendChild(createMark(className, fullText))
  65.                 item.appendChild(document.createTextNode(tailText || ''));
  66.             })
  67.         }
  68.  
  69.         function createMark(className, text) {
  70.             var mark = document.createElement('span');
  71.             mark.classList.add(className);
  72.             mark.appendChild(document.createTextNode(text.join('')));
  73.             return mark;
  74.         }
  75.  
  76.         function getChangedRows(className) {
  77.             var changedLines = Array.prototype.map.call(document.querySelectorAll('.' + className), function (element) {
  78.                 return element.parentElement;
  79.             });
  80.             changedLines = changedLines.filter(function (element) {
  81.                 return element.tagName == 'TD';
  82.             });
  83.             var lines = [];
  84.             for (var i = 0; i < changedLines.length; i++) {
  85.                 var line = changedLines[i];
  86.                 if (!lines.find(function (item) {
  87.                     return item == line;
  88.                 })) {
  89.                     lines.push(line);
  90.                 }
  91.             }
  92.             return lines;
  93.         }
  94.     </script>
  95. """
  96.  
  97. inject_styles = """
  98.     <style>
  99.         * {
  100.             font-size: 0.9rem !important;
  101.         }
  102.     </style>
  103. """
  104.  
  105.  
  106. def readlines(path):
  107.     """
  108.     讀取檔案內容
  109.     """
  110.     content = None
  111.     try:
  112.         with open(file=path, mode='rt', encoding='utf-8') as f:
  113.             content = [for l in f.readlines()]
  114.     except:
  115.         try:
  116.             with open(file=path, mode='rt', encoding='ms950') as f:
  117.                 content = [for l in f.readlines()]
  118.         except:
  119.             print('讀取 {} 失敗'.format(path))
  120.     return content
  121.  
  122.  
  123. def execute():
  124.     """
  125.     比對檔案產出 HTML
  126.     """
  127.     print('讀取檔案 {}'.format(to_file_path))
  128.     to_file_content = readlines(to_file_path)
  129.     print('讀取檔案 {}'.format(from_file_path))
  130.     from_file_content = readlines(from_file_path)
  131.  
  132.     if to_file_content is None or from_file_path is None:
  133.         return
  134.  
  135.     html = difflib.HtmlDiff().make_file(
  136.         from_file_content, to_file_content, from_file, to_file,  context=True)
  137.  
  138.     html = html.replace('</head>', inject_styles + '</head>')
  139.     html = html.replace('</body>', inject_script + '</body>')
  140.  
  141.     output_file = '{}.html'.format(to_file[0: to_file.find('\t')])
  142.     output_file = output_file.replace('/', '_')
  143.     output_file = output_file.replace('\\', '_')
  144.  
  145.     if len(to_file_content) == 0:
  146.         output_file = os.path.join(output_folder, FOLDER_DELETE, output_file)
  147.         if not os.path.exists(os.path.join(output_folder, FOLDER_DELETE)):
  148.             os.makedirs(os.path.join(output_folder, FOLDER_DELETE))
  149.     elif len(from_file_content) == 0:
  150.         output_file = os.path.join(output_folder, FOLDER_ADD, output_file)
  151.         if not os.path.exists(os.path.join(output_folder, FOLDER_ADD)):
  152.             os.makedirs(os.path.join(output_folder, FOLDER_ADD))
  153.     else:
  154.         output_file = os.path.join(output_folder, FOLDER_MODIFY, output_file)
  155.         if not os.path.exists(os.path.join(output_folder, FOLDER_MODIFY)):
  156.             os.makedirs(os.path.join(output_folder, FOLDER_MODIFY))
  157.  
  158.     print('寫入檔案 {}'.format(output_file))
  159.     with open(file=output_file, mode='wt', encoding='utf-8') as f:
  160.         f.write(html)
  161.  
  162.  
  163. if len([ext for ext in white_list if to_file[0: to_file.find('\t')].lower().endswith(ext.lower())]) > 0:
  164.     execute()
  165. else:
  166.     print('不處理 {} 的檔案比對。'.format(to_file[0: to_file.find('\t')]))

output file: