Patchwork [5,of,8,V2] hgweb: handle "linerange" request parameter in filediff command

login
register
mail settings
Submitter Denis Laxalde
Date Feb. 25, 2017, 9:06 a.m.
Message ID <7fbe70c91d65683ab398.1488013562@marimba>
Download mbox | patch
Permalink /patch/18774/
State Changes Requested
Headers show

Comments

Denis Laxalde - Feb. 25, 2017, 9:06 a.m.
# HG changeset patch
# User Denis Laxalde <denis.laxalde@logilab.fr>
# Date 1484922599 -3600
#      Fri Jan 20 15:29:59 2017 +0100
# Node ID 7fbe70c91d65683ab3984f7c80edc85f5c02860c
# Parent  6625dfbecf264f51748a96aa7203fc09bee597e9
# Available At https://hg.logilab.org/users/dlaxalde/hg
#              hg pull https://hg.logilab.org/users/dlaxalde/hg -r 7fbe70c91d65
# EXP-Topic linerange-log/hgweb-filelog
hgweb: handle "linerange" request parameter in filediff command

If a linerange=<fromline>:<toline> query parameter is present on a request to
filediff view we use this information to filter the diff to only display the
specified range of lines. This is achieved by getting the first "block
ancestor" of filectx and using it as the "basectx" in comparison along with
the pair of line ranges of both file contexts to generated a filtered diff.

Extra tests added in test-hgweb-diffs.t covering changes on hgweb side as well
as those in patch/mdiff of previous changesets.

Update only gitweb template in this version.
Yuya Nishihara - March 1, 2017, 2:50 p.m.
On Sat, 25 Feb 2017 10:06:02 +0100, Denis Laxalde wrote:
> # HG changeset patch
> # User Denis Laxalde <denis.laxalde@logilab.fr>
> # Date 1484922599 -3600
> #      Fri Jan 20 15:29:59 2017 +0100
> # Node ID 7fbe70c91d65683ab3984f7c80edc85f5c02860c
> # Parent  6625dfbecf264f51748a96aa7203fc09bee597e9
> # Available At https://hg.logilab.org/users/dlaxalde/hg
> #              hg pull https://hg.logilab.org/users/dlaxalde/hg -r 7fbe70c91d65
> # EXP-Topic linerange-log/hgweb-filelog
> hgweb: handle "linerange" request parameter in filediff command

> diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
> --- a/mercurial/hgweb/webcommands.py
> +++ b/mercurial/hgweb/webcommands.py
> @@ -762,7 +762,24 @@ def filediff(web, req, tmpl):
>      if 'style' in req.form:
>          style = req.form['style'][0]
>  
> -    diffs = webutil.diffs(web.repo, tmpl, ctx, basectx, [path], parity, style)
> +    lineranges = {}
> +    linerange = webutil.linerange(req)
> +    if linerange is not None:
> +        assert fctx is not None
> +        lineranges = {fctx: linerange}
> +        ancestors = context.blockancestors(fctx, *linerange, followfirst=True)
> +        try:
> +            next(ancestors)  # first iteration returns fctx
> +            p, plinerange = next(ancestors)
> +        except StopIteration:
> +            pass
> +        else:
> +            lineranges[p] = plinerange
> +            basectx = p.changectx()
> +        linerange = webutil.formatlinerange(*linerange)
> +
> +    diffs = webutil.diffs(web.repo, tmpl, ctx, basectx, [path], parity, style,
> +                          lineranges)
>      if fctx is not None:
>          rename = webutil.renamelink(fctx)
>          ctx = fctx
> @@ -774,6 +791,7 @@ def filediff(web, req, tmpl):
>                  symrev=webutil.symrevorshortnode(req, ctx),
>                  rename=rename,
>                  diff=diffs,
> +                linerange=linerange,
>                  **webutil.commonentry(web.repo, ctx))

I got a strange error. Can you take a look?

 1. run "hg serve" in mercurial repo
 2. open http://localhost:8000/annotate/tip/mercurial/cmdutil.py
 3. scroll down to the bottom
 4. click "follow lines" link of the last chunk
    http://localhost:8000/log/ed4d06f180b8/mercurial/cmdutil.py?linerange=3439:3475

We might use a wrong fctx/linerange pair.

Patch

diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -762,7 +762,24 @@  def filediff(web, req, tmpl):
     if 'style' in req.form:
         style = req.form['style'][0]
 
-    diffs = webutil.diffs(web.repo, tmpl, ctx, basectx, [path], parity, style)
+    lineranges = {}
+    linerange = webutil.linerange(req)
+    if linerange is not None:
+        assert fctx is not None
+        lineranges = {fctx: linerange}
+        ancestors = context.blockancestors(fctx, *linerange, followfirst=True)
+        try:
+            next(ancestors)  # first iteration returns fctx
+            p, plinerange = next(ancestors)
+        except StopIteration:
+            pass
+        else:
+            lineranges[p] = plinerange
+            basectx = p.changectx()
+        linerange = webutil.formatlinerange(*linerange)
+
+    diffs = webutil.diffs(web.repo, tmpl, ctx, basectx, [path], parity, style,
+                          lineranges)
     if fctx is not None:
         rename = webutil.renamelink(fctx)
         ctx = fctx
@@ -774,6 +791,7 @@  def filediff(web, req, tmpl):
                 symrev=webutil.symrevorshortnode(req, ctx),
                 rename=rename,
                 diff=diffs,
+                linerange=linerange,
                 **webutil.commonentry(web.repo, ctx))
 
 diff = webcommand('diff')(filediff)
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -430,7 +430,7 @@  def listfilediffs(tmpl, files, node, max
     if len(files) > max:
         yield tmpl('fileellipses')
 
-def diffs(repo, tmpl, ctx, basectx, files, parity, style):
+def diffs(repo, tmpl, ctx, basectx, files, parity, style, lineranges=None):
 
     def countgen():
         start = 1
@@ -466,7 +466,8 @@  def diffs(repo, tmpl, ctx, basectx, file
     node2 = ctx.node()
 
     block = []
-    for chunk in patch.diff(repo, node1, node2, m, opts=diffopts):
+    for chunk in patch.diff(repo, node1, node2, m, opts=diffopts,
+                            lineranges=lineranges):
         if chunk.startswith('diff') and block:
             blockno = next(blockcount)
             yield tmpl('diffblock', parity=next(parity), blockno=blockno,
diff --git a/mercurial/templates/gitweb/filediff.tmpl b/mercurial/templates/gitweb/filediff.tmpl
--- a/mercurial/templates/gitweb/filediff.tmpl
+++ b/mercurial/templates/gitweb/filediff.tmpl
@@ -33,7 +33,9 @@  diff |
 <br/>
 </div>
 
-<div class="title">{file|escape}</div>
+<div class="title">\
+{file|escape}{if(linerange, ' (line range: {linerange} <a href="{url|urlescape}diff/{symrev}/{file|urlescape}{sessionvars%urlparameter}">full diff</a>)')}\
+</div>
 
 <table>
 {branch%filerevbranch}
diff --git a/tests/test-hgweb-diffs.t b/tests/test-hgweb-diffs.t
--- a/tests/test-hgweb-diffs.t
+++ b/tests/test-hgweb-diffs.t
@@ -1094,6 +1094,305 @@  comparison not-modified file
   </body>
   </html>
   
+  $ cat <<EOF > c
+  > 1
+  > 2
+  > 3
+  > 4
+  > 5
+  > 6
+  > EOF
+  $ hg ci -Amc c
+  $ cat <<EOF > c
+  > 1
+  > 2+
+  > 3
+  > 4
+  > 5-
+  > 6
+  > EOF
+  $ hg ci -m 'update c' c
+  $ get-with-headers.py localhost:$HGPORT 'diff/tip/c?style=gitweb'
+  200 Script output follows
+  
+  <?xml version="1.0" encoding="ascii"?>
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+  <head>
+  <link rel="icon" href="/static/hgicon.png" type="image/png" />
+  <meta name="robots" content="index, nofollow"/>
+  <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
+  <script type="text/javascript" src="/static/mercurial.js"></script>
+  
+  <title>test: diff c</title>
+  <link rel="alternate" type="application/atom+xml"
+     href="/atom-log" title="Atom feed for test"/>
+  <link rel="alternate" type="application/rss+xml"
+     href="/rss-log" title="RSS feed for test"/>
+  </head>
+  <body>
+  
+  <div class="page_header">
+  <a href="https://mercurial-scm.org/" title="Mercurial" style="float: right;">Mercurial</a>
+  <a href="/">Mercurial</a>  / diff
+  </div>
+  
+  <div class="page_nav">
+  <a href="/summary?style=gitweb">summary</a> |
+  <a href="/shortlog?style=gitweb">shortlog</a> |
+  <a href="/log?style=gitweb">changelog</a> |
+  <a href="/graph?style=gitweb">graph</a> |
+  <a href="/tags?style=gitweb">tags</a> |
+  <a href="/bookmarks?style=gitweb">bookmarks</a> |
+  <a href="/branches?style=gitweb">branches</a> |
+  <a href="/file/tip?style=gitweb">files</a> |
+  <a href="/rev/tip?style=gitweb">changeset</a> |
+  <a href="/file/tip/c?style=gitweb">file</a> |
+  <a href="/file/tip/c?style=gitweb">latest</a> |
+  <a href="/log/tip/c?style=gitweb">revisions</a> |
+  <a href="/annotate/tip/c?style=gitweb">annotate</a> |
+  diff |
+  <a href="/comparison/tip/c?style=gitweb">comparison</a> |
+  <a href="/raw-diff/tip/c">raw</a> |
+  <a href="/help?style=gitweb">help</a>
+  <br/>
+  </div>
+  
+  <div class="title">c</div>
+  
+  <table>
+  
+  <tr>
+   <td>changeset 7</td>
+   <td style="font-family:monospace"><a class="list" href="/rev/46dadddbce95?style=gitweb">46dadddbce95</a></td>
+  </tr>
+  
+  <tr>
+  <td>parent 6</td>
+  <td style="font-family:monospace">
+  <a class="list" href="/diff/3deb5080745a/c?style=gitweb">
+  3deb5080745a
+  </a>
+  </td>
+  </tr>
+  
+  </table>
+  
+  <div class="list_head"></div>
+  
+  <div class="page_body">
+  <div class="diffblock"><pre class="sourcelines">
+  <a href="#l1.1"></a><span id="l1.1" class="difflineminus">--- a/c</span>
+  <a href="#l1.2"></a><span id="l1.2" class="difflineplus">+++ b/c</span>
+  <a href="#l1.3"></a><span id="l1.3" class="difflineat">@@ -1,6 +1,6 @@</span>
+  <a href="#l1.4"></a><span id="l1.4"> 1</span>
+  <a href="#l1.5"></a><span id="l1.5" class="difflineminus">-2</span>
+  <a href="#l1.6"></a><span id="l1.6" class="difflineplus">+2+</span>
+  <a href="#l1.7"></a><span id="l1.7"> 3</span>
+  <a href="#l1.8"></a><span id="l1.8"> 4</span>
+  <a href="#l1.9"></a><span id="l1.9" class="difflineminus">-5</span>
+  <a href="#l1.10"></a><span id="l1.10" class="difflineplus">+5-</span>
+  <a href="#l1.11"></a><span id="l1.11"> 6</span></pre></div>
+  </div>
+  
+  <div class="page_footer">
+  <div class="page_footer_text">test</div>
+  <div class="rss_logo">
+  <a href="/rss-log">RSS</a>
+  <a href="/atom-log">Atom</a>
+  </div>
+  <br />
+  
+  </div>
+  </body>
+  </html>
+  
+  $ get-with-headers.py localhost:$HGPORT 'diff/tip/c?style=gitweb&linerange=1:3'
+  200 Script output follows
+  
+  <?xml version="1.0" encoding="ascii"?>
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+  <head>
+  <link rel="icon" href="/static/hgicon.png" type="image/png" />
+  <meta name="robots" content="index, nofollow"/>
+  <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
+  <script type="text/javascript" src="/static/mercurial.js"></script>
+  
+  <title>test: diff c</title>
+  <link rel="alternate" type="application/atom+xml"
+     href="/atom-log" title="Atom feed for test"/>
+  <link rel="alternate" type="application/rss+xml"
+     href="/rss-log" title="RSS feed for test"/>
+  </head>
+  <body>
+  
+  <div class="page_header">
+  <a href="https://mercurial-scm.org/" title="Mercurial" style="float: right;">Mercurial</a>
+  <a href="/">Mercurial</a>  / diff
+  </div>
+  
+  <div class="page_nav">
+  <a href="/summary?style=gitweb">summary</a> |
+  <a href="/shortlog?style=gitweb">shortlog</a> |
+  <a href="/log?style=gitweb">changelog</a> |
+  <a href="/graph?style=gitweb">graph</a> |
+  <a href="/tags?style=gitweb">tags</a> |
+  <a href="/bookmarks?style=gitweb">bookmarks</a> |
+  <a href="/branches?style=gitweb">branches</a> |
+  <a href="/file/tip?style=gitweb">files</a> |
+  <a href="/rev/tip?style=gitweb">changeset</a> |
+  <a href="/file/tip/c?style=gitweb">file</a> |
+  <a href="/file/tip/c?style=gitweb">latest</a> |
+  <a href="/log/tip/c?style=gitweb">revisions</a> |
+  <a href="/annotate/tip/c?style=gitweb">annotate</a> |
+  diff |
+  <a href="/comparison/tip/c?style=gitweb">comparison</a> |
+  <a href="/raw-diff/tip/c">raw</a> |
+  <a href="/help?style=gitweb">help</a>
+  <br/>
+  </div>
+  
+  <div class="title">c (line range: 1:3 <a href="/diff/tip/c?style=gitweb">full diff</a>)</div>
+  
+  <table>
+  
+  <tr>
+   <td>changeset 7</td>
+   <td style="font-family:monospace"><a class="list" href="/rev/46dadddbce95?style=gitweb">46dadddbce95</a></td>
+  </tr>
+  
+  <tr>
+  <td>parent 6</td>
+  <td style="font-family:monospace">
+  <a class="list" href="/diff/3deb5080745a/c?style=gitweb">
+  3deb5080745a
+  </a>
+  </td>
+  </tr>
+  
+  </table>
+  
+  <div class="list_head"></div>
+  
+  <div class="page_body">
+  <div class="diffblock"><pre class="sourcelines">
+  <a href="#l1.1"></a><span id="l1.1" class="difflineminus">--- a/c</span>
+  <a href="#l1.2"></a><span id="l1.2" class="difflineplus">+++ b/c</span>
+  <a href="#l1.3"></a><span id="l1.3" class="difflineat">@@ -1,5 +1,5 @@</span>
+  <a href="#l1.4"></a><span id="l1.4"> 1</span>
+  <a href="#l1.5"></a><span id="l1.5" class="difflineminus">-2</span>
+  <a href="#l1.6"></a><span id="l1.6" class="difflineplus">+2+</span>
+  <a href="#l1.7"></a><span id="l1.7"> 3</span>
+  <a href="#l1.8"></a><span id="l1.8"> 4</span>
+  <a href="#l1.9"></a><span id="l1.9"> 5</span></pre></div>
+  </div>
+  
+  <div class="page_footer">
+  <div class="page_footer_text">test</div>
+  <div class="rss_logo">
+  <a href="/rss-log">RSS</a>
+  <a href="/atom-log">Atom</a>
+  </div>
+  <br />
+  
+  </div>
+  </body>
+  </html>
+  
+  $ get-with-headers.py localhost:$HGPORT 'diff/tip/c?style=gitweb&linerange=3:6'
+  200 Script output follows
+  
+  <?xml version="1.0" encoding="ascii"?>
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+  <head>
+  <link rel="icon" href="/static/hgicon.png" type="image/png" />
+  <meta name="robots" content="index, nofollow"/>
+  <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
+  <script type="text/javascript" src="/static/mercurial.js"></script>
+  
+  <title>test: diff c</title>
+  <link rel="alternate" type="application/atom+xml"
+     href="/atom-log" title="Atom feed for test"/>
+  <link rel="alternate" type="application/rss+xml"
+     href="/rss-log" title="RSS feed for test"/>
+  </head>
+  <body>
+  
+  <div class="page_header">
+  <a href="https://mercurial-scm.org/" title="Mercurial" style="float: right;">Mercurial</a>
+  <a href="/">Mercurial</a>  / diff
+  </div>
+  
+  <div class="page_nav">
+  <a href="/summary?style=gitweb">summary</a> |
+  <a href="/shortlog?style=gitweb">shortlog</a> |
+  <a href="/log?style=gitweb">changelog</a> |
+  <a href="/graph?style=gitweb">graph</a> |
+  <a href="/tags?style=gitweb">tags</a> |
+  <a href="/bookmarks?style=gitweb">bookmarks</a> |
+  <a href="/branches?style=gitweb">branches</a> |
+  <a href="/file/tip?style=gitweb">files</a> |
+  <a href="/rev/tip?style=gitweb">changeset</a> |
+  <a href="/file/tip/c?style=gitweb">file</a> |
+  <a href="/file/tip/c?style=gitweb">latest</a> |
+  <a href="/log/tip/c?style=gitweb">revisions</a> |
+  <a href="/annotate/tip/c?style=gitweb">annotate</a> |
+  diff |
+  <a href="/comparison/tip/c?style=gitweb">comparison</a> |
+  <a href="/raw-diff/tip/c">raw</a> |
+  <a href="/help?style=gitweb">help</a>
+  <br/>
+  </div>
+  
+  <div class="title">c (line range: 3:6 <a href="/diff/tip/c?style=gitweb">full diff</a>)</div>
+  
+  <table>
+  
+  <tr>
+   <td>changeset 7</td>
+   <td style="font-family:monospace"><a class="list" href="/rev/46dadddbce95?style=gitweb">46dadddbce95</a></td>
+  </tr>
+  
+  <tr>
+  <td>parent 6</td>
+  <td style="font-family:monospace">
+  <a class="list" href="/diff/3deb5080745a/c?style=gitweb">
+  3deb5080745a
+  </a>
+  </td>
+  </tr>
+  
+  </table>
+  
+  <div class="list_head"></div>
+  
+  <div class="page_body">
+  <div class="diffblock"><pre class="sourcelines">
+  <a href="#l1.1"></a><span id="l1.1" class="difflineminus">--- a/c</span>
+  <a href="#l1.2"></a><span id="l1.2" class="difflineplus">+++ b/c</span>
+  <a href="#l1.3"></a><span id="l1.3" class="difflineat">@@ -2,5 +2,5 @@</span>
+  <a href="#l1.4"></a><span id="l1.4"> 2</span>
+  <a href="#l1.5"></a><span id="l1.5"> 3</span>
+  <a href="#l1.6"></a><span id="l1.6"> 4</span>
+  <a href="#l1.7"></a><span id="l1.7" class="difflineminus">-5</span>
+  <a href="#l1.8"></a><span id="l1.8" class="difflineplus">+5-</span>
+  <a href="#l1.9"></a><span id="l1.9"> 6</span></pre></div>
+  </div>
+  
+  <div class="page_footer">
+  <div class="page_footer_text">test</div>
+  <div class="rss_logo">
+  <a href="/rss-log">RSS</a>
+  <a href="/atom-log">Atom</a>
+  </div>
+  <br />
+  
+  </div>
+  </body>
+  </html>
+  
   $ cd ..
 
 test import rev as raw-rev