Patchwork [2,of,3,V2] hgweb: display blamed revision once per block in annotate view

login
register
mail settings
Submitter Denis Laxalde
Date June 9, 2016, 12:34 p.m.
Message ID <04658d400e7f667f70a6.1465475697@sh77.tls.logilab.fr>
Download mbox | patch
Permalink /patch/15448/
State Changes Requested
Headers show

Comments

Denis Laxalde - June 9, 2016, 12:34 p.m.
# HG changeset patch
# User Denis Laxalde <denis.laxalde@logilab.fr>
# Date 1465294201 -7200
#      Tue Jun 07 12:10:01 2016 +0200
# Node ID 04658d400e7f667f70a639f919f6ff45dcccb52a
# Parent  3064963ddbc0b509c0f3f8149ca2c6edb2edb568
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."
Denis Laxalde - June 9, 2016, 12:54 p.m.
Denis Laxalde a écrit :
> # HG changeset patch
> # User Denis Laxalde<denis.laxalde@logilab.fr>
> # Date 1465294201 -7200
> #      Tue Jun 07 12:10:01 2016 +0200
> # Node ID 04658d400e7f667f70a639f919f6ff45dcccb52a
> # Parent  3064963ddbc0b509c0f3f8149ca2c6edb2edb568
> hgweb: display blamed revision once per block in annotate view

Note that this patch is new in the series (was not in V1), though it 
follows up on the same topic.
Augie Fackler - June 10, 2016, 3:36 a.m.
On Thu, Jun 09, 2016 at 02:34:57PM +0200, Denis Laxalde wrote:
> # HG changeset patch
> # User Denis Laxalde <denis.laxalde@logilab.fr>
> # Date 1465294201 -7200
> #      Tue Jun 07 12:10:01 2016 +0200
> # Node ID 04658d400e7f667f70a639f919f6ff45dcccb52a
> # Parent  3064963ddbc0b509c0f3f8149ca2c6edb2edb568
> hgweb: display blamed revision once per block in annotate view

I really like this. I tried to apply this as-is, but it appears to not apply
without patch 1. I look forward to v3 that addresses Anton's feedback. Thanks!

>
> 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."
>
> diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
> --- a/mercurial/hgweb/webcommands.py
> +++ b/mercurial/hgweb/webcommands.py
> @@ -873,15 +873,20 @@ def annotate(web, req, tmpl):
>          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,
>                     "blamedrev": blamedrev,
>                     "author": f.user(),
>                     "desc": f.description(),
>                     "extra": f.extra(),
>                     "file": f.path(),
> +                   "blockhead": blockhead,
>                     "targetline": targetline,
>                     "line": l,
>                     "lineno": lineno + 1,
> diff --git a/mercurial/templates/gitweb/map b/mercurial/templates/gitweb/map
> --- a/mercurial/templates/gitweb/map
> +++ b/mercurial/templates/gitweb/map
> @@ -97,9 +97,11 @@ fileline = '
>  annotateline = '
>    <tr id="{lineid}" style="font-family:monospace" class="parity{parity}">
>      <td class="linenr" style="text-align: right;">
> -      <a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
> -         {ifeq(rev, blamedrev, 'class="blamedrev"', '')}
> -         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}"
> +              {ifeq(rev, blamedrev, 'class="blamedrev"', '')}
> +              title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>',
> +          '')}
>      </td>
>      <td><pre><a class="linenr" href="#{lineid}">{linenumber}</a></pre></td>
>      <td><pre{ifeq(rev, blamedrev, ' class="blamedrev"', '')}>{line|escape}</pre></td>
> diff --git a/mercurial/templates/monoblue/map b/mercurial/templates/monoblue/map
> --- a/mercurial/templates/monoblue/map
> +++ b/mercurial/templates/monoblue/map
> @@ -93,8 +93,10 @@ fileline = '
>  annotateline = '
>    <tr id="{lineid}" class="parity{parity}">
>      <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>
> diff --git a/mercurial/templates/paper/map b/mercurial/templates/paper/map
> --- a/mercurial/templates/paper/map
> +++ b/mercurial/templates/paper/map
> @@ -78,8 +78,10 @@ filelogentry = filelogentry.tmpl
>  annotateline = '
>    <tr id="{lineid}">
>      <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>'
> diff --git a/mercurial/templates/spartan/map b/mercurial/templates/spartan/map
> --- a/mercurial/templates/spartan/map
> +++ b/mercurial/templates/spartan/map
> @@ -56,8 +56,10 @@ filelogentry = filelogentry.tmpl
>  annotateline = '
>    <tr class="parity{parity}">
>      <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>
> diff --git a/tests/test-highlight.t b/tests/test-highlight.t
> --- a/tests/test-highlight.t
> +++ b/tests/test-highlight.t
> @@ -297,225 +297,193 @@ hgweb fileannotate, html
>    </tr>
>    <tr id="l2">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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">
>    <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>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -873,15 +873,20 @@  def annotate(web, req, tmpl):
         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,
                    "blamedrev": blamedrev,
                    "author": f.user(),
                    "desc": f.description(),
                    "extra": f.extra(),
                    "file": f.path(),
+                   "blockhead": blockhead,
                    "targetline": targetline,
                    "line": l,
                    "lineno": lineno + 1,
diff --git a/mercurial/templates/gitweb/map b/mercurial/templates/gitweb/map
--- a/mercurial/templates/gitweb/map
+++ b/mercurial/templates/gitweb/map
@@ -97,9 +97,11 @@  fileline = '
 annotateline = '
   <tr id="{lineid}" style="font-family:monospace" class="parity{parity}">
     <td class="linenr" style="text-align: right;">
-      <a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
-         {ifeq(rev, blamedrev, 'class="blamedrev"', '')}
-         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}"
+              {ifeq(rev, blamedrev, 'class="blamedrev"', '')}
+              title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>',
+          '')}
     </td>
     <td><pre><a class="linenr" href="#{lineid}">{linenumber}</a></pre></td>
     <td><pre{ifeq(rev, blamedrev, ' class="blamedrev"', '')}>{line|escape}</pre></td>
diff --git a/mercurial/templates/monoblue/map b/mercurial/templates/monoblue/map
--- a/mercurial/templates/monoblue/map
+++ b/mercurial/templates/monoblue/map
@@ -93,8 +93,10 @@  fileline = '
 annotateline = '
   <tr id="{lineid}" class="parity{parity}">
     <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>
diff --git a/mercurial/templates/paper/map b/mercurial/templates/paper/map
--- a/mercurial/templates/paper/map
+++ b/mercurial/templates/paper/map
@@ -78,8 +78,10 @@  filelogentry = filelogentry.tmpl
 annotateline = '
   <tr id="{lineid}">
     <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>'
diff --git a/mercurial/templates/spartan/map b/mercurial/templates/spartan/map
--- a/mercurial/templates/spartan/map
+++ b/mercurial/templates/spartan/map
@@ -56,8 +56,10 @@  filelogentry = filelogentry.tmpl
 annotateline = '
   <tr class="parity{parity}">
     <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>
diff --git a/tests/test-highlight.t b/tests/test-highlight.t
--- a/tests/test-highlight.t
+++ b/tests/test-highlight.t
@@ -297,225 +297,193 @@  hgweb fileannotate, html
   </tr>
   <tr id="l2">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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">
   <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>