hgweb: display blamed revision once per block in annotate view
authorDenis Laxalde <denis.laxalde@logilab.fr>
Tue, 07 Jun 2016 12:10:01 +0200
changeset 29388 f694e20193f2
parent 29387 6b77adc2c7b5
child 29389 98e8313dcd9e
hgweb: display blamed revision once per block in annotate view I.e. when a revision blames a block of source lines, only display the revision link on the first line of the block (this is identified by the "blockhead" key in annotate context). This addresses item "Visual grouping of changesets" of the blame improvements plan (https://www.mercurial-scm.org/wiki/BlamePlan) which states: "Typically there are block of lines all attributed to the same revision. Instead of rendering the revision/changeset for every line, we could only render it once per block."
mercurial/hgweb/webcommands.py
mercurial/templates/gitweb/map
mercurial/templates/monoblue/map
mercurial/templates/paper/map
mercurial/templates/spartan/map
tests/test-highlight.t
--- a/mercurial/hgweb/webcommands.py	Thu Jun 02 16:26:50 2016 +0200
+++ b/mercurial/hgweb/webcommands.py	Tue Jun 07 12:10:01 2016 +0200
@@ -872,14 +872,19 @@
         else:
             lines = enumerate(fctx.annotate(follow=True, linenumber=True,
                                             diffopts=diffopts))
+        previousrev = None
         for lineno, ((f, targetline), l) in lines:
+            rev = f.rev()
+            blockhead = rev != previousrev or None
+            previousrev = rev
             yield {"parity": next(parity),
                    "node": f.hex(),
-                   "rev": f.rev(),
+                   "rev": rev,
                    "author": f.user(),
                    "desc": f.description(),
                    "extra": f.extra(),
                    "file": f.path(),
+                   "blockhead": blockhead,
                    "targetline": targetline,
                    "line": l,
                    "lineno": lineno + 1,
--- a/mercurial/templates/gitweb/map	Thu Jun 02 16:26:50 2016 +0200
+++ b/mercurial/templates/gitweb/map	Tue Jun 07 12:10:01 2016 +0200
@@ -97,8 +97,10 @@
 annotateline = '
   <tr id="{lineid}" style="font-family:monospace" class="parity{parity}{ifeq(node, originalnode, ' thisrev')}">
     <td class="linenr" style="text-align: right;">
-      <a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
-         title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
+      {if(blockhead,
+          '<a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
+              title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>',
+          '')}
     </td>
     <td><pre><a class="linenr" href="#{lineid}">{linenumber}</a></pre></td>
     <td><pre>{line|escape}</pre></td>
--- a/mercurial/templates/monoblue/map	Thu Jun 02 16:26:50 2016 +0200
+++ b/mercurial/templates/monoblue/map	Tue Jun 07 12:10:01 2016 +0200
@@ -93,8 +93,10 @@
 annotateline = '
   <tr id="{lineid}" class="parity{parity}{ifeq(node, originalnode, ' thisrev')}">
     <td class="linenr">
-      <a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
-         title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
+      {if(blockhead,
+          '<a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
+              title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>',
+          '')}
     </td>
     <td class="lineno">
       <a href="#{lineid}">{linenumber}</a>
--- a/mercurial/templates/paper/map	Thu Jun 02 16:26:50 2016 +0200
+++ b/mercurial/templates/paper/map	Tue Jun 07 12:10:01 2016 +0200
@@ -78,8 +78,10 @@
 annotateline = '
   <tr id="{lineid}"{ifeq(node, originalnode, ' class="thisrev"')}>
     <td class="annotate">
-      <a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
-         title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
+      {if(blockhead,
+          '<a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
+              title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>',
+          '')}
     </td>
     <td class="source"><a href="#{lineid}">{linenumber}</a> {line|escape}</td>
   </tr>'
--- a/mercurial/templates/spartan/map	Thu Jun 02 16:26:50 2016 +0200
+++ b/mercurial/templates/spartan/map	Tue Jun 07 12:10:01 2016 +0200
@@ -56,8 +56,10 @@
 annotateline = '
   <tr class="parity{parity}{ifeq(node, originalnode, ' thisrev')}">
     <td class="annotate">
-      <a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
-         title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
+      {if(blockhead,
+          '<a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
+              title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>',
+          '')}
     </td>
     <td>
       <a class="lineno" href="#{lineid}" id="{lineid}">{linenumber}</a>
--- a/tests/test-highlight.t	Thu Jun 02 16:26:50 2016 +0200
+++ b/tests/test-highlight.t	Tue Jun 07 12:10:01 2016 +0200
@@ -297,225 +297,193 @@
   </tr>
   <tr id="l2" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l2"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l2">     2</a> </td>
   </tr>
   <tr id="l3" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l3"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l3">     3</a> <span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span></td>
   </tr>
   <tr id="l4" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l4"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l4">     4</a> </td>
   </tr>
   <tr id="l5" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l5"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l5">     5</a> <span class="sd">primes = 2 : sieve [3, 5..]</span></td>
   </tr>
   <tr id="l6" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l6"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l6">     6</a> <span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span></td>
   </tr>
   <tr id="l7" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l7"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l7">     7</a> <span class="sd">&quot;&quot;&quot;</span></td>
   </tr>
   <tr id="l8" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l8"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l8">     8</a> </td>
   </tr>
   <tr id="l9" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l9"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l9">     9</a> <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span></td>
   </tr>
   <tr id="l10" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l10"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l10">    10</a> </td>
   </tr>
   <tr id="l11" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l11"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l11">    11</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></td>
   </tr>
   <tr id="l12" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l12"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l12">    12</a>     <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></td>
   </tr>
   <tr id="l13" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l13"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l13">    13</a>     <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td>
   </tr>
   <tr id="l14" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l14"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l14">    14</a>         <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></td>
   </tr>
   <tr id="l15" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l15"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l15">    15</a>         <span class="c"># It is important to yield *here* in order to stop the</span></td>
   </tr>
   <tr id="l16" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l16"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l16">    16</a>         <span class="c"># infinite recursion.</span></td>
   </tr>
   <tr id="l17" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l17"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l17">    17</a>         <span class="kn">yield</span> <span class="n">p</span></td>
   </tr>
   <tr id="l18" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l18"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l18">    18</a>         <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></td>
   </tr>
   <tr id="l19" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l19"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l19">    19</a>         <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td>
   </tr>
   <tr id="l20" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l20"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l20">    20</a>             <span class="kn">yield</span> <span class="n">n</span></td>
   </tr>
   <tr id="l21" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l21"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l21">    21</a> </td>
   </tr>
   <tr id="l22" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l22"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l22">    22</a>     <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span></td>
   </tr>
   <tr id="l23" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l23"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l23">    23</a>     <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></td>
   </tr>
   <tr id="l24" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l24"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l24">    24</a> </td>
   </tr>
   <tr id="l25" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l25"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l25">    25</a> <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span></td>
   </tr>
   <tr id="l26" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l26"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l26">    26</a>     <span class="kn">import</span> <span class="nn">sys</span></td>
   </tr>
   <tr id="l27" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l27"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l27">    27</a>     <span class="kn">try</span><span class="p">:</span></td>
   </tr>
   <tr id="l28" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l28"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l28">    28</a>         <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></td>
   </tr>
   <tr id="l29" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l29"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l29">    29</a>     <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></td>
   </tr>
   <tr id="l30" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l30"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l30">    30</a>         <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></td>
   </tr>
   <tr id="l31" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l31"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l31">    31</a>     <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></td>
   </tr>
   <tr id="l32" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l32"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l32">    32</a>     <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></td>
   </tr>
   <tr id="l33" class="thisrev">
   <td class="annotate">
-  <a href="/annotate/06824edf55d0/primes.py#l33"
-  title="06824edf55d0: a">test@0</a>
+  
   </td>
   <td class="source"><a href="#l33">    33</a> </td>
   </tr>