[diffoscope] 01/01: In split-html output, also split individual diffs that are too long
Ximin Luo
infinity0 at debian.org
Wed Aug 24 20:48:22 CEST 2016
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch better-lazy-loading
in repository diffoscope.
commit 2750887c40df1a278afd3e6b6852f3ba901ccf96
Author: Ximin Luo <infinity0 at debian.org>
Date: Wed Aug 24 20:47:46 2016 +0200
In split-html output, also split individual diffs that are too long
---
diffoscope/presenters/html.py | 170 +++++++++++++++++++++++++++++++-----------
1 file changed, 127 insertions(+), 43 deletions(-)
diff --git a/diffoscope/presenters/html.py b/diffoscope/presenters/html.py
index be8b145..5968860 100644
--- a/diffoscope/presenters/html.py
+++ b/diffoscope/presenters/html.py
@@ -149,7 +149,7 @@ HEADER = """<!DOCTYPE html>
.diffheader:hover .anchor {
display: inline;
}
- .ondemand {
+ .ondemand, .ondemand-cont {
text-align: center;
}
</style>
@@ -168,16 +168,29 @@ SCRIPTS = """
<script src="%(jquery_url)s"></script>
<script type="text/javascript">
$(function() {
- $("div.ondemand a").on('click', function (){
+ var cont_click = function() {
+ var filename = $(this).attr('href');
+ var div = $(this).parent();
+ div.text('... loading ...');
+ div.parent().load(filename + " tr", function() {
+ // http://stackoverflow.com/a/8452751/946226
+ $(this).children(':first').unwrap();
+ $(".ondemand-cont a").on('click', cont_click);
+ });
+ return false;
+ };
+ $(".ondemand a").on('click', function (){
var filename = $(this).attr('href');
var div = $(this).parent();
div.text('... loading ...');
div.load(filename + " table", function() {
// http://stackoverflow.com/a/8452751/946226
$(this).children(':first').unwrap();
+ $(".ondemand-cont a").on('click', cont_click);
});
return false;
});
+ $(".ondemand-cont a").on('click', cont_click);
});
</script>
"""
@@ -197,10 +210,17 @@ def create_limited_print_func(print_func, max_page_size):
return limited_print_func
+def estimate_num_rows_per_page(separate_file_diff_size):
+ # each row takes about 1200 bytes in the output, so roughly calculate
+ # the number of rows that 4 * separate_file_diff_size will hold
+ return separate_file_diff_size * 4 // 1200
+
buf = []
add_cpt, del_cpt = 0, 0
line1, line2 = 0, 0
hunk_off1, hunk_size1, hunk_off2, hunk_size2 = 0, 0, 0, 0
+rows_output, diff_table_current_page = 0, 0
+row_print_func, row_print_ctrl = None, None
def sane(x):
@@ -317,12 +337,13 @@ def convert(s, ponct=0, tag=''):
return t.getvalue()
-def output_hunk(print_func):
- print_func(u'<tr class="diffhunk"><td colspan="2">Offset %d, %d lines modified</td>'%(hunk_off1, hunk_size1))
- print_func(u'<td colspan="2">Offset %d, %d lines modified</td></tr>\n'%(hunk_off2, hunk_size2))
+def output_hunk():
+ row_print_func(u'<tr class="diffhunk"><td colspan="2">Offset %d, %d lines modified</td>'%(hunk_off1, hunk_size1))
+ row_print_func(u'<td colspan="2">Offset %d, %d lines modified</td></tr>\n'%(hunk_off2, hunk_size2))
+ row_was_output()
-def output_line(print_func, s1, s2):
+def output_line(s1, s2):
global line1
global line2
@@ -348,25 +369,26 @@ def output_line(print_func, s1, s2):
type_name = "changed"
s1, s2 = linediff(s1, s2)
- print_func(u'<tr class="diff%s">' % type_name)
+ row_print_func(u'<tr class="diff%s">' % type_name)
try:
if s1:
- print_func(u'<td class="diffline">%d </td>' % line1)
- print_func(u'<td class="diffpresent">')
- print_func(convert(s1, ponct=1, tag='del'))
- print_func(u'</td>')
+ row_print_func(u'<td class="diffline">%d </td>' % line1)
+ row_print_func(u'<td class="diffpresent">')
+ row_print_func(convert(s1, ponct=1, tag='del'))
+ row_print_func(u'</td>')
else:
- print_func(u'<td colspan="2">\xa0</td>')
+ row_print_func(u'<td colspan="2">\xa0</td>')
if s2:
- print_func(u'<td class="diffline">%d </td>' % line2)
- print_func(u'<td class="diffpresent">')
- print_func(convert(s2, ponct=1, tag='ins'))
- print_func(u'</td>')
+ row_print_func(u'<td class="diffline">%d </td>' % line2)
+ row_print_func(u'<td class="diffpresent">')
+ row_print_func(convert(s2, ponct=1, tag='ins'))
+ row_print_func(u'</td>')
else:
- print_func(u'<td colspan="2">\xa0</td>')
+ row_print_func(u'<td colspan="2">\xa0</td>')
finally:
- print_func(u"</tr>\n", force=True)
+ row_print_func(u"</tr>\n", force=True)
+ row_was_output()
m = orig1 and re.match(r"^\[ (\d+) lines removed \]$", orig1)
if m:
@@ -380,14 +402,14 @@ def output_line(print_func, s1, s2):
line2 += 1
-def empty_buffer(print_func):
+def empty_buffer():
global buf
global add_cpt
global del_cpt
if del_cpt == 0 or add_cpt == 0:
for l in buf:
- output_line(print_func, l[0], l[1])
+ output_line(l[0], l[1])
elif del_cpt != 0 and add_cpt != 0:
l0, l1 = [], []
@@ -403,44 +425,99 @@ def empty_buffer(print_func):
s0 = l0[i]
if i < len(l1):
s1 = l1[i]
- output_line(print_func, s0, s1)
+ output_line(s0, s1)
add_cpt, del_cpt = 0, 0
buf = []
-def output_unified_diff_table(print_func, unified_diff):
+def row_print_enter(print_context, rotation_params):
+ # Takes ownership of print_context
+ global row_print_func, row_print_ctrl
+ row_print_ctrl = print_context.__exit__, rotation_params
+ row_print_func = print_context.__enter__()
+
+def row_print_exit_exc():
+ global row_print_func, row_print_ctrl
+ row_print_exit, _ = row_print_ctrl
+ row_print_func, row_print_ctrl = None, None
+ return row_print_exit(*sys.exc_info())
+
+def row_print_exit_else():
+ global row_print_func, row_print_ctrl
+ row_print_exit, _ = row_print_ctrl
+ row_print_func, row_print_ctrl = None, None
+ row_print_exit(None, None, None)
+
+def row_was_output():
+ global row_print_func, row_print_ctrl, rows_output, diff_table_current_page
+ rows_output += 1
+ _, rotation_params = row_print_ctrl
+ directory, mainname, css_url, rows_per_page = rotation_params
+ if rows_output % rows_per_page != 0:
+ return
+ diff_table_current_page += 1
+
+ filename = "%s-%s.html" % (mainname, diff_table_current_page)
+ # close the current page
+ row_print_func("<tr class='ondemand-cont'><td colspan='4'>\n")
+ row_print_func("... <a href='%s'>load diff</a> ...\n" % escape(filename))
+ row_print_func("</td></tr>\n")
+ row_print_func(u"</table>", force=True)
+ output_footer(row_print_func)
+ row_print_exit_else()
+ # rotate to the next page
+ context = file_printer(directory, filename)
+ row_print_enter(context, rotation_params)
+ output_header(css_url, row_print_func)
+ row_print_func(u'<table class="diff">\n')
+ row_print_func(u'<colgroup><col style="width: 3em;"/><col style="99%"/>\n')
+ row_print_func(u'<col style="width: 3em;"/><col style="99%"/></colgroup>\n')
+
+ at contextlib.contextmanager
+def global_row_printer(print_context, rotation_params=None):
+ """Context manager that allows the context to be changed during the body."""
+ try:
+ row_print_enter(print_context, rotation_params)
+ yield row_print_func
+ except:
+ if not row_print_exit_exc():
+ raise
+ else:
+ row_print_exit_else()
+
+def output_unified_diff_table(unified_diff):
global add_cpt, del_cpt
global line1, line2
global hunk_off1, hunk_size1, hunk_off2, hunk_size2
- print_func(u'<table class="diff">\n')
+ row_print_func(u'<table class="diff">\n')
try:
- print_func(u'<colgroup><col style="width: 3em;"/><col style="99%"/>\n')
- print_func(u'<col style="width: 3em;"/><col style="99%"/></colgroup>\n')
+ row_print_func(u'<colgroup><col style="width: 3em;"/><col style="99%"/>\n')
+ row_print_func(u'<col style="width: 3em;"/><col style="99%"/></colgroup>\n')
for l in unified_diff.splitlines():
m = re.match(r'^--- ([^\s]*)', l)
if m:
- empty_buffer(print_func)
+ empty_buffer()
continue
m = re.match(r'^\+\+\+ ([^\s]*)', l)
if m:
- empty_buffer(print_func)
+ empty_buffer()
continue
m = re.match(r"@@ -(\d+),?(\d*) \+(\d+),?(\d*)", l)
if m:
- empty_buffer(print_func)
+ empty_buffer()
hunk_data = map(lambda x:x=="" and 1 or int(x), m.groups())
hunk_off1, hunk_size1, hunk_off2, hunk_size2 = hunk_data
line1, line2 = hunk_off1, hunk_off2
- output_hunk(print_func)
+ output_hunk()
continue
if re.match(r'^\[', l):
- empty_buffer(print_func)
- print_func(u'<td colspan="2">%s</td>\n' % l)
+ empty_buffer()
+ row_print_func(u'<td colspan="2">%s</td>\n' % l)
if re.match(r"^\\ No newline", l):
if hunk_size2 == 0:
@@ -450,7 +527,7 @@ def output_unified_diff_table(print_func, unified_diff):
continue
if hunk_size1 <= 0 and hunk_size2 <= 0:
- empty_buffer(print_func)
+ empty_buffer()
continue
m = re.match(r"^\+\[ (\d+) lines removed \]$", l)
@@ -480,34 +557,41 @@ def output_unified_diff_table(print_func, unified_diff):
continue
if re.match(r"^ ", l) and hunk_size1 and hunk_size2:
- empty_buffer(print_func)
+ empty_buffer()
hunk_size1 -= 1
hunk_size2 -= 1
buf.append((l[1:], l[1:]))
continue
- empty_buffer(print_func)
+ empty_buffer()
- empty_buffer(print_func)
+ empty_buffer()
finally:
- print_func(u"</table>", force=True)
+ row_print_func(u"</table>", force=True)
def output_unified_diff(print_func, css_url, directory, unified_diff):
if directory and len(unified_diff) > Config.general.separate_file_diff_size:
# open a new file for this table
- filename="%s.html" % hashlib.md5(unified_diff.encode('utf-8')).hexdigest()
+ mainname = hashlib.md5(unified_diff.encode('utf-8')).hexdigest()
+ filename="%s.html" % mainname
logger.debug('separate html output for diff of size %d', len(unified_diff))
- with file_printer(directory, filename) as new_print_func:
- output_header(css_url, new_print_func)
- output_unified_diff_table(new_print_func, unified_diff)
- output_footer(new_print_func)
+ num_pages = 0
+ global row_print_func, diff_table_current_page
+ rows_per_page = estimate_num_rows_per_page(Config.general.separate_file_diff_size)
+ rotation_params = directory, mainname, css_url, rows_per_page
+ with global_row_printer(file_printer(directory, filename), rotation_params):
+ output_header(css_url, row_print_func)
+ output_unified_diff_table(unified_diff)
+ output_footer(row_print_func)
+ num_pages = diff_table_current_page + 1
print_func("<div class='ondemand'>\n")
- print_func("... <a href='%s'>load diff</a> ...\n" % escape(filename))
+ print_func("... <a href='%s'>load diff (%s pieces) </a> ...\n" % (escape(filename), num_pages))
print_func("</div>\n")
else:
- output_unified_diff_table(print_func, unified_diff)
+ with global_row_printer(print_func):
+ output_unified_diff_table(unified_diff)
def output_difference(difference, print_func, css_url, directory, parents):
logger.debug('html output for %s', difference.source1)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git
More information about the diffoscope
mailing list