From 1c93532b5c4cebc96c01227d6ed0da7414fc0751 Mon Sep 17 00:00:00 2001 From: zPlus Date: Mon, 8 Aug 2022 08:00:16 +0200 Subject: [PATCH] Allow expandable diffs in commit page. Allow expansion and shrinkage of diffed files in the commit page. --- static/css/clif.css | 56 ++++++++++------ templates/repository/commit.html | 108 +++++++++++++++++-------------- web.py | 10 ++- 3 files changed, 103 insertions(+), 71 deletions(-) diff --git a/static/css/clif.css b/static/css/clif.css index 5c82909..a8afbad 100644 --- a/static/css/clif.css +++ b/static/css/clif.css @@ -393,67 +393,87 @@ div.commit { margin-top: .5rem; } - div.commit .diff { + div.commit details.diff_view { + border: 1px solid black; border: 1px solid #d4d4d4; + box-shadow: 0 .5rem 1rem -.5rem #ccc; + margin-top: 1rem; + position: relative; + } + + div.commit details.diff_view summary { + background-color: #f7f7f7; + border-bottom: 1px solid #d4d4d4; + list-style: none; + padding: .2rem; + } + + div.commit details.diff_view summary:after { + content: "➕"; + position: absolute; + right: .5rem; + top: .5rem; + transition: 100ms linear; + } + + div.commit details.diff_view[open] summary:after { + transform: rotate(45deg); + } + + div.commit details.diff_view .diff { border-collapse: collapse; border-spacing: 0; font-family: monospace; font-size: 1rem; - margin-top: 2rem; width: 100%; } - div.commit .diff thead { - background-color: #f7f7f7; - border: 1px solid #d4d4d4; - } - - div.commit .diff td { + div.commit details.diff_view .diff td { padding: .1rem .5rem; } - div.commit .diff .histogram { + div.commit details.diff_view .diff .histogram { border-bottom: .3rem solid; display: inline-block; vertical-align: middle; } - div.commit .diff .header { + div.commit details.diff_view .diff .header { background-color: #f0f9ff; color: darkblue; } - div.commit .diff .header td { + div.commit details.diff_view .diff .header td { padding: .5rem .5rem; } - div.commit .diff .lineno { + div.commit details.diff_view .diff .lineno { color: gray; text-align: center; width: 0; } - div.commit .diff .origin { + div.commit details.diff_view .diff .origin { width: 0; } - div.commit .diff .deletion { + div.commit details.diff_view .diff .deletion { background-color: #ffeef0; } - div.commit .diff .insertion { + div.commit details.diff_view .diff .insertion { background-color: #e6ffed; } - div.commit .diff .change { + div.commit details.diff_view .diff .change { background-color: #feffbe; } - div.commit .diff .content { + div.commit details.diff_view .diff .content { white-space: pre-wrap; } - div.commit .diff .ssdiff .content { + div.commit details.diff_view .diff .ssdiff .content { width: 50%; } diff --git a/templates/repository/commit.html b/templates/repository/commit.html index 7973425..f89aea7 100644 --- a/templates/repository/commit.html +++ b/templates/repository/commit.html @@ -60,7 +60,7 @@



-
+
{# pygit2 appears to recompute all the stats every time we use diff.stats, # therefore we set this variable in order to compute it only once. #} @@ -91,7 +91,7 @@
-
+
Diff options
@@ -147,8 +147,8 @@ {% for patch in diff %} -
- +
+ {# The following status values are defined in the git_delta_t enum # in libgit2. See https://github.com/libgit2/libgit2/blob/main/include/git2/diff.h # 0 = UNCHANGED @@ -159,40 +159,38 @@ # 5 = COPIED # ... (there are other codes that we don't use) #} -
- - - + + {% if patch.line_stats[1] + patch.line_stats[2] > 0 %} + {% set color_border = patch.line_stats[1] / ( patch.line_stats[1] + patch.line_stats[2] ) * 100 %} + {% else %} + {% set color_border = 0 %} + {% endif %} + + + +{{ patch.line_stats[1] }}/-{{ patch.line_stats[2] }} + + + {% if patch.delta.status == 1 %} + A {{ patch.delta.new_file.path }} + {% endif %} + + {% if patch.delta.status == 2 %} + D {{ patch.delta.old_file.path }} + {% endif %} + + {% if patch.delta.status == 3 %} + M {{ patch.delta.new_file.path }} + {% endif %} + + {% if patch.delta.status == 4 %} + R {{ patch.delta.old_file.path }} -> {{ patch.delta.new_file.path }} + {% endif %} + + {% if patch.delta.status == 5 %} + C {{ patch.delta.old_file.path }} {{ patch.delta.new_file.path }} + {% endif %} + +
- {% if patch.line_stats[1] + patch.line_stats[2] > 0 %} - {% set color_border = patch.line_stats[1] / ( patch.line_stats[1] + patch.line_stats[2] ) * 100 %} - {% else %} - {% set color_border = 0 %} - {% endif %} - - - +{{ patch.line_stats[1] }}/-{{ patch.line_stats[2] }} - - - {% if patch.delta.status == 1 %} - A {{ patch.delta.new_file.path }} - {% endif %} - - {% if patch.delta.status == 2 %} - D {{ patch.delta.old_file.path }} - {% endif %} - - {% if patch.delta.status == 3 %} - M {{ patch.delta.new_file.path }} - {% endif %} - - {% if patch.delta.status == 4 %} - R {{ patch.delta.old_file.path }} -> {{ patch.delta.new_file.path }} - {% endif %} - - {% if patch.delta.status == 5 %} - C {{ patch.delta.old_file.path }} {{ patch.delta.new_file.path }} - {% endif %} -
- - +
old size: {{ patch.delta.old_file.size|human_size(B=true) }} @@ -213,8 +211,10 @@ {% endif %}
+ + + {% if patch.delta.is_binary %} @@ -254,8 +255,15 @@ {% endif %} {#### SSDIFF mode ####} + {# In this mode, changed lines are buffered until we find an + # unchanged line. When an unchanged line has been found, the + # buffer is emptied. + #} {% if mode == 'ssdiff' %} + {% set buffer_deletions = [] %} + {% set buffer_insertions = [] %} + {% macro print_buffer(buffer_deletions, buffer_insertions) %} {% for buffer_del, buffer_ins in zip_longest(buffer_deletions, buffer_insertions) %} @@ -283,9 +291,9 @@ {% endfor %} - {# .clear() empties the buffer. However since it requires - # {{}} brackets instead of {%%}, this line will print the - # value of "buffer_deletions" which is "None". + {# .clear() empties the buffer. Since this requires {{}} + # brackets instead of {%%}, this line will print the value + # of "buffer_deletions" which is "None". # "or ''" is a hack for printing an empty line instead of "None". #} {{ buffer_deletions.clear() or '' }} @@ -296,9 +304,6 @@ - {% set buffer_deletions = [] %} - {% set buffer_insertions = [] %} - {% for line in hunk.lines %} {% if line.old_lineno < 0 %} {{ buffer_insertions.append(line) or '' }} @@ -313,6 +318,7 @@ {# Unload buffer #} {{ print_buffer(buffer_deletions, buffer_insertions) }} + {# Insert the unchanged line. #} - -
@@ -226,6 +226,7 @@ {% for hunk in patch.hunks if not patch.delta.is_binary %} {#### UDIFF mode ####} + {# In this mode the lines are printed one after the other. #} {% if mode == 'udiff' %}
{{ hunk.header }}
{{ line.old_lineno }} @@ -327,14 +333,16 @@ {% endif %} {% endfor %} - {# Empty remaining buffer #} + {# Empty remaining buffer. There is a non-empty buffer if we did + # not find an unchanged line, for example when context_lines=0. + #} {{ print_buffer(buffer_deletions, buffer_insertions) }} {% endif %} {% endfor %} -
+ + +
{% endfor %} diff --git a/web.py b/web.py index 62a2060..1e36c61 100644 --- a/web.py +++ b/web.py @@ -44,13 +44,15 @@ INSTANCE_DOMAIN = 'domain.local' # How many commits to show in the log page LOG_PAGINATION = 100 -# Default options when showing diffs in "commit" page +# Default options for showing diffs in "commit" page DIFF_VIEW = 'udiff' # "udiff", "ssdiff" DIFF_CONTEXT_LINES = 3 DIFF_INTERHUNK_LINES = 0 -DIFF_SHOW_DIFFSTAT = False DIFF_SIDE = 'normal' # "normal", "reverse" DIFF_WHITESPACE = 'include' # "include", "ignore_all", "ignore_change", "ignore_eol" +DIFF_EXPAND = True # Show expanded diff files by default +DIFF_EXPAND_DIFFSTAT = False +DIFF_EXPAND_DIFFOPTIONS = False @@ -177,7 +179,9 @@ template = functools.partial(template, template_settings = { 'url': application.get_url, 'zip_longest': itertools.zip_longest, 'defaults': { - 'DIFF_SHOW_DIFFSTAT': DIFF_SHOW_DIFFSTAT + 'DIFF_EXPAND': DIFF_EXPAND, + 'DIFF_EXPAND_DIFFSTAT': DIFF_EXPAND_DIFFSTAT, + 'DIFF_EXPAND_DIFFOPTIONS': DIFF_EXPAND_DIFFOPTIONS } }, 'autoescape': True