You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by tv...@apache.org on 2012/12/18 05:29:29 UTC

[12/41] git commit: [#5389] ticket:229 use own side-by-side diff generator

[#5389] ticket:229 use own side-by-side diff generator


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/ba6c028f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/ba6c028f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/ba6c028f

Branch: refs/heads/tv/4957
Commit: ba6c028fda9e6d8b048faf11cfa4e339c866eaf0
Parents: b09028b
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri Dec 7 12:56:02 2012 +0000
Committer: Cory Johns <jo...@geek.net>
Committed: Mon Dec 17 22:21:16 2012 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/repository.py |    5 +-
 Allura/allura/lib/diff.py               |   96 ++++++++++++++++++++++++++
 2 files changed, 99 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba6c028f/Allura/allura/controllers/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index d93fe1d..853fda9 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -31,6 +31,7 @@ from allura.lib.widgets.subscriptions import SubscribeForm
 from allura import model as M
 from allura.lib.widgets import form_fields as ffw
 from allura.controllers.base import DispatchIndex
+from allura.lib.diff import HtmlSideBySideDiff
 
 from .base import BaseController
 
@@ -586,8 +587,8 @@ class FileBrowser(BaseController):
             web_session['diformat'] = fmt
             web_session.save()
         if fmt == 'sidebyside':
-            hd = difflib.HtmlDiff(tabsize=4)
-            diff = hd.make_table(la, lb, adesc, bdesc, context=True)
+            hd = HtmlSideBySideDiff()
+            diff = hd.make_table(la, lb, adesc, bdesc)
             diff = diff.replace('&nbsp;', ' ')
         else:
             diff = ''.join(difflib.unified_diff(la, lb, adesc, bdesc))

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba6c028f/Allura/allura/lib/diff.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/diff.py b/Allura/allura/lib/diff.py
new file mode 100644
index 0000000..78a736b
--- /dev/null
+++ b/Allura/allura/lib/diff.py
@@ -0,0 +1,96 @@
+import difflib
+
+
+class HtmlSideBySideDiff(object):
+
+    table_tmpl = '''
+<table class="side-by-side-diff">
+  <thead>
+    <th colspan="2">%s</th>
+    <th colspan="2">%s</th>
+  </thead>
+  %s
+</table>
+'''.strip()
+
+    line_tmpl = '''
+<tr>
+  <td class="lineno">%s</td>
+  <td%s><pre>%s</pre></td>
+  <td class="lineno">%s</td>
+  <td%s><pre>%s</pre></td>
+</tr>'''.strip()
+
+    def __init__(self, tabsize=4):
+        self._tabsize = 4
+
+    def _render_change(self, aline, bline, anum=None, bnum=None, astyle=None, bstyle=None):
+        astyle = (' class="%s"' % astyle) if astyle else ''
+        bstyle = (' class="%s"' % bstyle) if bstyle else ''
+        anum = anum if anum is not None else ''
+        bnum = bnum if bnum is not None else ''
+        return self.line_tmpl % (anum, astyle, aline, bnum, bstyle, bline)
+
+    def _preprocess(self, line):
+        if not line:
+            return line
+        line = line.expandtabs(self._tabsize)
+        return line.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+
+    def _replace_marks(self, line):
+        # if entire line was added/removed/changed
+        # we strip first mark and return corresponding flag
+        # this is needed to be able to highlight entire <td> in the table,
+        # rather then highlighting only chunk inside the <span>
+        flag = ''
+        if line.startswith('\0+'):
+            line = line.lstrip('\0+').rstrip('\1')
+            flag = 'diff-add'
+        elif line.startswith('\0-'):
+            line = line.lstrip('\0-').rstrip('\1')
+            flag = 'diff-rem'
+        elif '\0^' in line:
+            flag = 'diff-chg'
+
+        # replace all other marks with <span>'s
+        span = '<span class="%s">'
+        line = line.replace('\0+', span % 'diff-add')
+        line = line.replace('\0-', span % 'diff-rem')
+        line = line.replace('\0^', span % 'diff-chg')
+        line = line.replace('\1', '</span>')
+        return line, flag
+
+    def _make_line(self, diff):
+        aline, bline, changed = diff
+        if changed is None:
+            # context separation
+            return self._render_change('...', '...', '', '', 'diff-gap', 'diff-gap')
+        anum, aline = aline
+        bnum, bline = bline
+        aline = self._preprocess(aline)
+        bline = self._preprocess(bline)
+        if not changed:
+            # line doesn't changed - render with default style
+            return self._render_change(aline, bline, anum, bnum)
+
+        aline, aflag = self._replace_marks(aline)
+        bline, bflag = self._replace_marks(bline)
+        return self._render_change(aline, bline, anum, bnum, aflag, bflag)
+
+    def make_table(self, a, b, adesc=None, bdesc=None, context=5):
+        """Make html table that displays side-by-side diff
+
+        Arguments:
+         - a -- list of text lines to be compared to b
+         - b -- list of text lines to be compared to a
+         - adesc -- description of the 'a' lines (e.g. filename)
+         - bdesc -- description of the 'b' lines (e.g. filename)
+         - context -- number of context lines to display
+
+        Uses difflib._mdiff function to generate diff.
+        """
+        adesc = adesc or ''
+        bdesc = bdesc or ''
+        diff = difflib._mdiff(a, b, context=context)
+        lines = [self._make_line(d) for d in diff]
+        return self.table_tmpl % (adesc, bdesc, '\n'.join(lines))