add image ks file diff feature
authorShan Jin <shanx.jin@intel.com>
Tue, 24 Dec 2013 05:28:34 +0000 (13:28 +0800)
committerShan Jin <shanx.jin@intel.com>
Wed, 25 Dec 2013 02:40:54 +0000 (10:40 +0800)
- add few methods to parse the diff info in image.py.
- add new template to show the ks diff.

Change-Id: I7d8b71a63a09088f4a8e756b4a8791b4e6088ac9
Fixes: #1567
snapdiff/__init__.py
snapdiff/image.py
snapdiff/static/css/diff.css [new file with mode: 0644]
snapdiff/templates/diff.html
snapdiff/templates/image_diff.html [new file with mode: 0644]

index 84b1c0466f617eb7513456fdc391e9fd66061b79..aeb85cb04d8892f7f26951c762fcf4f373f86c73 100644 (file)
@@ -28,6 +28,7 @@ __version__ = '0.1'
 import json
 import os
 import shutil
+import re
 
 from .image import ks_diff, packages
 from .render import output_html
@@ -160,7 +161,7 @@ def diff_to_JSON(old_url, new_url, style='repo'):
             }
 
     if style == 'image':
-        obj['diff']['ks'] = ''.join([d for d in ks_diff(old_url, new_url)])
+        obj['diff']['ks'] = ks_diff(old_url, new_url)
 
     return json.dumps(obj, indent=4)
 
@@ -174,12 +175,17 @@ def diff_to_HTML(old_url, new_url, style='repo'):
 
     data = json.loads(json_obj)
 
-    context = {'old_url': old_url,
-            'new_url': new_url,
-            'diff': data['diff'],
-            }
-
-    return output_html('diff.html', **context)
+    context = {
+        'old': {'url': old_url,
+            'name': re.search('\w*_\d{8}\.\d*', old_url).group(0)},
+        'new': {'url': new_url,
+            'name': re.search('\w*_\d{8}\.\d*', new_url).group(0)},
+        'diff': data['diff'],
+        }
+    if style == 'repo':
+        return output_html('diff.html', **context)
+    elif style == 'image':
+        return output_html('image_diff.html', **context)
 
 def diff_to_dist(old_url, new_url, dist_path, style='repo'):
     """create a dist-dir of diffs, contains html and css"""
index c22efc049eb980c2913ad96fff45b8042480fdd5..e52dbf1bd29b42420982ccbac7ed8087156f111c 100644 (file)
@@ -33,12 +33,117 @@ def _get_file(url, suffix='.ks'):
 
     return '', ''
 
+def _parse_range(line):
+    '''Start and Count'''
+    def parse_start_count(chars):
+        '''Count ommit when it's 1'''
+        start, count = chars[1:].split(',')
+        return int(start), int(count)
+
+    _, delete, insert, _ = line.split()
+    return {
+        'delete': parse_start_count(delete),
+        'insert': parse_start_count(insert),
+        }
+
+def _parse_hunks(arr, range_):
+    '''Hunks'''
+    count = 0
+    hunks = []
+    left_start = range_['delete'][0]
+    right_start = range_['insert'][0]
+    for line in arr:
+        if line.startswith('+++') or line.startswith('---'):
+            count += 1
+            continue
+        elif line.startswith(' '):
+            type_ = 'context'
+            hunk = {'type':'context',
+                    'left_num':left_start,
+                    'right_num':right_start,
+                    'text':line[1:-1]}
+            left_start += 1
+            right_start += 1
+        elif line.startswith('-'):
+            type_ = 'delete'
+            hunk = {}
+            for right_line in arr[count:]:
+                if right_line.startswith(' '):
+                    hunk = {'type':'delete',
+                            'left_num':left_start,
+                            'left_text':line[1:-1]}
+                    left_start += 1
+                    break
+                elif right_line.startswith('+'):
+                    hunk = {'type':'change',
+                            'left_num':left_start,
+                            'right_num':right_start,
+                            'left_text':line[1:-1],
+                            'right_text':right_line[1:-1]}
+                    arr.remove(right_line)
+                    left_start += 1
+                    right_start += 1
+                    break
+            if not hunk:
+                hunk = {'type':'delete',
+                        'left_num':left_start,
+                        'left_text':line[1:-1]}
+                left_start += 1
+        elif line.startswith('+'):
+            type_ = 'insert'
+            hunk = {'type':type_,
+                    'right_num':right_start,
+                    'right_text':line[1:-1]}
+            right_start += 1
+        else:
+            break
+        hunks.append(hunk)
+        count += 1
+    return hunks
+
+def _parse_sections(stream):
+    sections = []
+    stack = []
+    head_stack = ''
+    def parse_range_hunks(line):
+        print head_stack
+        range_ = _parse_range(head_stack)
+        hunks = _parse_hunks(stack, range_)
+        stack = []
+        head_stack = line
+        sections.append({
+            'hunks': hunks
+            })
+    for line in stream:
+        if not line.startswith('@@ '):
+            stack.append(line)
+            continue
+        if not head_stack:
+            head_stack = line
+            continue
+        range_ = _parse_range(head_stack)
+        hunks = _parse_hunks(stack, range_)
+        sections.append({
+            'hunks': hunks
+            })
+        stack = []
+        head_stack = line
+    if stack and head_stack:
+        range_ = _parse_range(head_stack)
+        hunks = _parse_hunks(stack, range_)
+        sections.append({
+            'hunks': hunks
+            })
+    return sections
+
 def ks_diff(old, new):
     ks_old, ks_new = _get_file(old), _get_file(new)
+    diff_list = []
 
-    for line in difflib.unified_diff(ks_old[1], ks_new[1], fromfile=ks_old[0],
-            tofile=ks_new[0]):
-        yield line
+    stream = difflib.unified_diff(ks_old[1], ks_new[1], fromfile=ks_old[0], tofile=ks_new[0])
+    for section in _parse_sections(stream):
+        diff_list.append(section)
+    return {'file_name': [ks_old[0], ks_new[0]], 'sections': diff_list}
 
 def packages(url):
     content = _get_file(url, suffix='.packages')
diff --git a/snapdiff/static/css/diff.css b/snapdiff/static/css/diff.css
new file mode 100644 (file)
index 0000000..c383798
--- /dev/null
@@ -0,0 +1,36 @@
+.ks_diff{
+    border-bottom: 1px solid #B0BDCC;
+}
+ul {
+    padding: 0;
+    margin: 0;
+    list-style-type: none;
+}
+.ks_diff td {
+    border: none;
+    background-color: white;
+}
+
+.ks_diff .code_insert {
+    background-color: #DDFFDD;
+}
+.ks_diff .code_delete {
+    background-color: #FFEEEE;
+}
+.ks_diff .content {
+    border-left: thin solid #B0BDCC;
+    border-right: thin solid #B0BDCC;
+}
+.ks_diff .nocontent {
+    background-color: #EEEEEE;
+}
+.modifLi {
+    list-style-type: disc;
+    padding-left:1em;
+}
+.tableTitle {
+    background-color: white;
+    border: none;
+    font-size: 1.3em;
+    padding-left: 0;
+}
index 708e6d61db7c4699fe91365aa4b23b7962159560..4a62a6ceac3d4e8057cba0d962af1aaf6d4743dd 100644 (file)
@@ -8,6 +8,7 @@
     <link href="./css/style.css" media="screen" rel="stylesheet" type="text/css" />
     <link href="./css/shCore.css" rel="stylesheet" type="text/css" />
     <link href="./css/shThemeDefault.css" rel="stylesheet" type="text/css" />
+    <link href="./css/diff.css" rel="stylesheet" type="text/css" />
 </head>
 <body>
     <div id="page-wrapper">
@@ -26,7 +27,7 @@
     </h1>
     <a href="index.html">Go back</a>...<br>
     <p>Difference between
-        <a href="{{old_url}}">{{ old_url }}</a> and <a href="{{new_url}}">{{ new_url }}</a>
+        <a href="{{old['url']}}">{{ old['name'] }}</a> and <a href="{{new['url']}}">{{ new['name'] }}</a>
     </p>
     <h3>Highlights</h3>
     <ul>
                     <td>{{ item['oldpkg']['version']['ver'] }}-{{item['oldpkg']['version']['rel']}}~{{ item['newpkg']['version']['ver'] }}-{{item['newpkg']['version']['rel']}}</td>
                     <td>
                         <ul>
-                            <li>{{ item['oldpkg']['git_path'] }}</li>
-                            <li>{{ item['newpkg']['git_path'] }}</li>
+                            {% if item['oldpkg']['git_path'] != item['newpkg']['git_path'] %}
+                                <li>{{ item['oldpkg']['git_path'] }}&nbsp;</li>
+                                <li>{{ item['newpkg']['git_path'] }}&nbsp;</li>
+                            {% else %}
+                                <li>{{ item['oldpkg']['git_path'] }}</li>
+                            {% endif %}
                         </ul>
                     </td>
                     <td>
-                        <ul>
+                        <ul class="modifLi">
                             <li>{{ item['oldpkg']['commit_id'] }}</li>
                             <li>{{ item['newpkg']['commit_id'] }}</li>
                         </ul>
diff --git a/snapdiff/templates/image_diff.html b/snapdiff/templates/image_diff.html
new file mode 100644 (file)
index 0000000..dc49dae
--- /dev/null
@@ -0,0 +1,165 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <link href="./css/html-reset.css" media="screen" rel="stylesheet" type="text/css" />
+    <link href="./css/layout-liquid.css" media="screen" rel="stylesheet" type="text/css" />
+    <link href="./css/tizen.css" media="screen" rel="stylesheet" type="text/css" />
+    <link href="./css/style.css" media="screen" rel="stylesheet" type="text/css" />
+    <link href="./css/shCore.css" rel="stylesheet" type="text/css" />
+    <link href="./css/shThemeDefault.css" rel="stylesheet" type="text/css" />
+    <link href="./css/diff.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+    <div id="page-wrapper">
+      <div id="page">
+        <div id="header">
+          <div class="section clearfix">
+            <h1 id="logo">
+              <a href="http://www.tizen.org"><img alt="Tizen-logo" src="./img/tizen-logo.png" width="180px" height="50px"></a>
+            </h1>
+          </div>
+        </div>
+      </div>
+    </div>
+    <h1>
+        Repository Difference and Changelogs
+    </h1>
+    <a href="index.html">Go back</a>...<br>
+    <p>Difference between
+        <a href="{{old['url']}}">{{ old['name'] }}</a> and <a href="{{new['url']}}">{{ new['name'] }}</a>
+    </p>
+    <h3>KS</h3>
+    {% if diff['ks'] %}
+        <table class="ks_diff">
+            <tr><th></th><th>{{diff['ks']['file_name'][0]}}</th><th>{{diff['ks']['file_name'][1]}}</th><th></th></tr>
+            {% if diff['ks']['sections'] %}
+                {% for section in diff['ks']['sections'] %}
+                    {% for hunk in section['hunks'] %}
+                        {% if hunk['type'] == "context" %}
+                        <tr>
+                            <td class="left_num">{{hunk['left_num']}}</td>
+                            <td class="context content">{{hunk['text']}}</td>
+                            <td class="context content">{{hunk['text']}}</td>
+                            <td class="right_num">{{hunk['right_num']}}</td>
+                        </tr>
+                        {% elif hunk['type'] == "delete" %}
+                        <tr>
+                            <td class="left_num">{{hunk['left_num']}}</td>
+                            <td class="code_delete content">{{hunk['ileft_text']}}</td>
+                            <td class="nocontent content"></td>
+                            <td class="right_num"></td>
+                        </tr>
+                        {% elif hunk['type'] == "insert" %}
+                        <tr>
+                            <td class="left_num"></td>
+                            <td class="nocontent content"></td>
+                            <td class="code_insert content">{{hunk['right_text']}}</td>
+                            <td class="right_num">{{hunk['right_num']}}</td>
+                        </tr>
+                        {% elif hunk['type'] == "change" %}
+                        <tr>
+                            <td class="left_num">{{hunk['left_num']}}</td>
+                            <td class="code_delete content">{{hunk['left_text']}}</td>
+                            <td class="code_insert content">{{hunk['right_text']}}</td>
+                            <td class="right_num">{{hunk['right_num']}}</td>
+                        </tr>
+                        {% endif %}
+                    {% endfor %}
+                    {% if not loop.last %}
+                        <tr><td>&nbsp;</td><td class="nocontent content">&nbsp;</td><td class="nocontent content">&nbsp;</td><td>&nbsp;</td></tr>
+                    {% endif %}
+                {% endfor %}
+            {% endif %}
+        </table>
+    {% endif %}
+    <h3>Highlights</h3>
+    <ul>
+        <li><a href="#added">Added Packages: {{ diff['added']|count }}</a></li>
+        <li><a href="#removed">Removed Packages: {{ diff['removed']|count }}</a></li>
+        <li><a href="#modified">Modified packages: {{ diff['modified']|count }}</a></li>
+        <li><a href="#rebuilded">Packages with Rebuilds: {{ diff['rebuilded']|count }}</a></li>
+    </ul>
+    <table>
+        <tr><td colspan="4" class="tableTitle"><h3><a>Added Packages</a></h3></td></tr>
+        {% if diff['added'] %}
+            <tbody>
+            <tr>
+                <th>Package</th><th>Version</th><th>GitPath</th><th>CommitId</th>
+            </tr>
+            {% for item in diff['added'] %}
+                <tr>
+                    <td>{{ item['newpkg']['name'] }}</td>
+                    <td>{{ item['newpkg']['version']['ver'] }}-{{item['newpkg']['version']['rel']}}</td>
+                    <td>{{ item['newpkg']['git_path'] }}</td>
+                    <td>{{ item['newpkg']['commit_id'] }}</td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        {% endif %}
+        <tr><td colspan="4" class="tableTitle"><h3><a>Removed Packages</a></h3></td></tr>
+        {% if diff['removed'] %}
+            <tbody>
+            <tr>
+                <th>Package</th><th>Version</th><th>GitPath</th><th>CommitId</th>
+            </tr>
+            {% for item in diff['removed'] %}
+                <tr>
+                    <td>{{ item['oldpkg']['name'] }}</td>
+                    <td>{{ item['oldpkg']['version']['ver'] }}-{{item['oldpkg']['version']['rel']}}</td>
+                    <td>{{ item['oldpkg']['git_path'] }}</td>
+                    <td>{{ item['oldpkg']['commit_id'] }}</td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        {% endif %}
+        <tr><td colspan="4" class="tableTitle"><h3><a>Modified Packages</a></h3></td></tr>
+        {% if diff['modified'] %}
+            <tbody>
+            <tr>
+                <th>Package</th><th>Version</th><th>GitPath</th><th>CommitId</th>
+            </tr>
+            {% for item in diff['modified'] %}
+                <tr>
+                    <td>{{ item['oldpkg']['name'] }}</td>
+                    <td>{{ item['oldpkg']['version']['ver'] }}-{{item['oldpkg']['version']['rel']}}~{{ item['newpkg']['version']['ver'] }}-{{item['newpkg']['version']['rel']}}</td>
+                    <td>
+                        <ul>
+                            {% if item['oldpkg']['git_path'] != item['newpkg']['git_path'] %}
+                                <li>{{ item['oldpkg']['git_path'] }}&nbsp;</li>
+                                <li>{{ item['newpkg']['git_path'] }}&nbsp;</li>
+                            {% else %}
+                                <li>{{ item['oldpkg']['git_path'] }}</li>
+                            {% endif %}
+                        </ul>
+                    </td>
+                    <td>
+                        <ul class="modifLi">
+                            <li>{{ item['oldpkg']['commit_id'] }}</li>
+                            <li>{{ item['newpkg']['commit_id'] }}</li>
+                        </ul>
+                    </td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        {% endif %}
+        <tr><td colspan="4" class="tableTitle"><h3><a>Packages with Rebuilds</a></h3></td></tr>
+        {% if diff['rebuilded'] %}
+        <tbody>
+            <tr>
+                <th>Package</th><th>Version</th><th>GitPath</th><th>CommitId</th>
+            </tr>
+            {% for item in diff['rebuilded'] %}
+                <tr>
+                    <td>{{ item['oldpkg']['name'] }}</td>
+                    <td>{{ item['oldpkg']['version']['ver'] }}-{{item['oldpkg']['version']['rel']}}~{{ item['newpkg']['version']['ver'] }}-{{item['newpkg']['version']['rel']}}</td>
+                    <td>{{ item['oldpkg']['git_path'] }}</td>
+                    <td>{{ item['oldpkg']['commit_id'] }}</td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        {% endif %}
+    </table>
+</body>
+</html>
+