[PATCH] changeset: add filename derived anchors to file diffs (and use them)

Angel Ezquerra angel.ezquerra at gmail.com
Sun Feb 21 20:59:50 UTC 2016


# HG changeset patch
# User Angel Ezquerra <angel.ezquerra at gmail.com>
# Date 1456088218 -3600
#      Sun Feb 21 21:56:58 2016 +0100
# Branch stable
# Node ID f1e465120793c9c7cad6baa4d78a00155bac4311
# Parent  f7b771cc04c39f5d49b7b82397bd594db7285693
changeset: add filename derived anchors to file diffs (and use them)

Up until now it was not possible to create direct links to the file diffs within
a changeset page because those links were created based on each file FID (which
users cannot easily guess).

This changeset adds anchors to each file diff. Each anchor name is derived from
the corresponding filepath, which has been encoded to make it suitable to be
used as URL anchor names as follows:

1. replace all forward slashes (/) with backward slashes (\)
2. (python urlib) URL quoting
3. replace all periods with exclamation marks

This encoding is necessary (particularly the \ to / and . to ! mapping) because
browsers have problems with anchors that contain forward slashes and periods.

Note that the original FID link targets have not been removed. Thus this change
should be transparent to the rest of Kallithea.

diff --git a/kallithea/lib/utils.py b/kallithea/lib/utils.py
--- a/kallithea/lib/utils.py
+++ b/kallithea/lib/utils.py
@@ -36,6 +36,7 @@
 import shutil
 import decorator
 import warnings
+import urllib
 from os.path import abspath
 from os.path import dirname as dn, join as jn
 
@@ -850,6 +851,22 @@
     return json.dumps(data, encoding='utf-8')
 
 
+def path2anchor(path):
+    """Encode a file path so that it can be used as an HTML anchor
+
+    In order to be able to use file paths as HTML anchors we must encode
+    them. Additionally, some browsers (e.g. Firefox and Chrome) behave
+    weirdly when navigating to an anchor whose name contains a period or
+    a forward slash. To avoid that problem this function also replaces
+    all forward slashes with backward slashes and all periods with
+    exclamation marks. We chose to replace periods with exclamation marks
+    because they are hard to miss when inspecting URLs.
+
+    :param path: file path that must be encoded
+    :return: encoded file path
+    """
+    return urllib.quote(path.replace('/','\\')).replace('.', '!')
+
 def conditional_cache(region, prefix, condition, func):
     """
 
diff --git a/kallithea/templates/changeset/changeset.html b/kallithea/templates/changeset/changeset.html
--- a/kallithea/templates/changeset/changeset.html
+++ b/kallithea/templates/changeset/changeset.html
@@ -17,6 +17,7 @@
 </%block>
 
 <%def name="main()">
+<%from kallithea.lib import utils%>
 ${self.repo_context_bar('changelog', c.changeset.raw_id)}
 <div class="box">
     <!-- box / title -->
@@ -173,7 +174,7 @@
                   <div class="cs_${change}">
                         <div class="node">
                             <i class="icon-diff-${change}"></i>
-                            <a href="#${FID}">${h.safe_unicode(path)}</a>
+                            <a href="#${utils.path2anchor(path)}">${h.safe_unicode(path)}</a>
                         </div>
                     <div class="changes">${h.fancy_file_stats(stats)}</div>
                   </div>
diff --git a/kallithea/templates/changeset/diff_block.html b/kallithea/templates/changeset/diff_block.html
--- a/kallithea/templates/changeset/diff_block.html
+++ b/kallithea/templates/changeset/diff_block.html
@@ -4,6 +4,7 @@
 ## ${diff_block.diff_block(change)}
 ##
 <%def name="diff_block(change)">
+<%from kallithea.lib import utils%>
 <div class="diff-collapse">
     <span target="${'diff-container-%s' % (id(change))}" class="diff-collapse-button">↑ ${_('Collapse Diff')} ↑</span>
 </div>
@@ -11,6 +12,7 @@
 %for FID,(cs1, cs2, change, path, diff, stats) in change.iteritems():
     <div id="${FID}_target" style="clear:both;margin-top:25px"></div>
     <div id="${FID}" class="diffblock  margined comm">
+        <a name="${utils.path2anchor(path)}"></a>
         <div class="code-header">
             <div class="changeset_header">
                 <div class="changeset_file">
-------------- next part --------------
A non-text attachment was scrubbed...
Name: kallithea.patch
Type: text/x-patch
Size: 4077 bytes
Desc: not available
URL: <http://lists.sfconservancy.org/pipermail/kallithea-general/attachments/20160221/f77d20c5/attachment.bin>


More information about the kallithea-general mailing list