[PATCH 2 of 8 V2] hgweb: handle a "linerange" request parameter in filelog command

Gregory Szorc gregory.szorc at gmail.com
Tue Feb 28 18:26:19 EST 2017


On Sat, Feb 25, 2017 at 1:05 AM, Denis Laxalde <denis at laxalde.org> wrote:

> # HG changeset patch
> # User Denis Laxalde <denis.laxalde at logilab.fr>
> # Date 1484844060 -3600
> #      Thu Jan 19 17:41:00 2017 +0100
> # Node ID 43d99fe8dcb510540db19366fcac8159d4e26691
> # Parent  17c6195ce42f3cbb47cee53aeb4e6a4e5074878a
> # Available At https://hg.logilab.org/users/dlaxalde/hg
> #              hg pull https://hg.logilab.org/users/dlaxalde/hg -r
> 43d99fe8dcb5
> # EXP-Topic linerange-log/hgweb-filelog
> hgweb: handle a "linerange" request parameter in filelog command
>
> We now handle a "linerange" URL query parameter to filter filelog using
> a logic similar to followlines() revset.
> The URL syntax is: log/<rev>/<file>?linerange=<fromline>:<toline>
> As a result, filelog entries only consists of revision changing specified
> line range.
>
> The linerange information is propagated to "more"/"less" navigation links
> but
> not to numeric navigation links as this would apparently require a
> dedicated
> "revnav" class.
>
> Only the gitweb template got updated for now.
>
> diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.
> py
> --- a/mercurial/hgweb/webcommands.py
> +++ b/mercurial/hgweb/webcommands.py
> @@ -28,6 +28,7 @@ from .common import (
>
>  from .. import (
>      archival,
> +    context,
>      encoding,
>      error,
>      graphmod,
> @@ -969,6 +970,8 @@ def filelog(web, req, tmpl):
>          except ValueError:
>              pass
>
> +    lrange = webutil.linerange(req)
> +
>      lessvars = copy.copy(tmpl.defaults['sessionvars'])
>      lessvars['revcount'] = max(revcount / 2, 1)
>      morevars = copy.copy(tmpl.defaults['sessionvars'])
> @@ -982,26 +985,48 @@ def filelog(web, req, tmpl):
>      repo = web.repo
>      revs = fctx.filelog().revs(start, end - 1)
>      entries = []
> -    for i in revs:
> -        iterfctx = fctx.filectx(i)
> -        entries.append(dict(
> -            parity=next(parity),
> -            filerev=i,
> -            file=f,
> -            rename=webutil.renamelink(iterfctx),
> -            **webutil.commonentry(repo, iterfctx)))
> -    entries.reverse()
> +    linerange = None
> +    if lrange is not None:
> +        linerange = webutil.formatlinerange(*lrange)
> +        # deactivate numeric nav links when linerange is specified as this
> +        # would required a dedicated "revnav" class
> +        nav = None
> +        ancestors = context.blockancestors(fctx, *lrange)
> +        for i, (c, lr) in enumerate(ancestors, 1):
> +            # follow renames accross filtered (not in range) revisions
> +            path = c.path()
> +            entries.append(dict(
> +                parity=next(parity),
> +                filerev=c.rev(),
> +                file=path,
> +                linerange=webutil.formatlinerange(*lr),
> +                **webutil.commonentry(repo, c)))
> +            if i == revcount:
> +                break
> +        lessvars['linerange'] = webutil.formatlinerange(*lrange)
> +        morevars['linerange'] = lessvars['linerange']
> +    else:
> +        for i in revs:
> +            iterfctx = fctx.filectx(i)
> +            entries.append(dict(
> +                parity=next(parity),
> +                filerev=i,
> +                file=f,
> +                rename=webutil.renamelink(iterfctx),
> +                **webutil.commonentry(repo, iterfctx)))
> +        entries.reverse()
> +        revnav = webutil.filerevnav(web.repo, fctx.path())
> +        nav = revnav.gen(end - 1, revcount, count)
>
>      latestentry = entries[:1]
>
> -    revnav = webutil.filerevnav(web.repo, fctx.path())
> -    nav = revnav.gen(end - 1, revcount, count)
>      return tmpl("filelog",
>                  file=f,
>                  nav=nav,
>                  symrev=webutil.symrevorshortnode(req, fctx),
>                  entries=entries,
>                  latestentry=latestentry,
> +                linerange=linerange,
>                  revcount=revcount,
>                  morevars=morevars,
>                  lessvars=lessvars,
> diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
> --- a/mercurial/hgweb/webutil.py
> +++ b/mercurial/hgweb/webutil.py
> @@ -18,6 +18,7 @@ from ..node import hex, nullid, short
>
>  from .common import (
>      ErrorResponse,
> +    HTTP_BAD_REQUEST,
>      HTTP_NOT_FOUND,
>      paritygen,
>  )
> @@ -313,6 +314,25 @@ def filectx(repo, req):
>
>      return fctx
>
> +def linerange(req):
> +    linerange = req.form.get('linerange')
> +    if linerange is None:
> +        return None
> +    if len(linerange) > 1:
> +        raise ErrorResponse(HTTP_BAD_REQUEST,
> +                            'redundant linerange parameter')
> +    try:
> +        try:
> +            fromline, toline = map(int, linerange[0].split(':', 1))
> +        except ValueError:
> +            raise ValueError('invalid linerange parameter')
> +        return util.processlinerange(fromline, toline)
> +    except ValueError as exc:
> +        raise ErrorResponse(HTTP_BAD_REQUEST, str(exc))
> +
> +def formatlinerange(fromline, toline):
> +    return '%d:%d' % (fromline + 1, toline)
> +
>  def commonentry(repo, ctx):
>      node = ctx.node()
>      return {
> diff --git a/mercurial/templates/gitweb/filelog.tmpl
> b/mercurial/templates/gitweb/filelog.tmpl
> --- a/mercurial/templates/gitweb/filelog.tmpl
> +++ b/mercurial/templates/gitweb/filelog.tmpl
> @@ -31,7 +31,9 @@ revisions |
>  {nav%filenav}
>  </div>
>
> -<div class="title" >{file|urlescape}</div>
> +<div class="title">{file|urlescape}{if(linerange,
> +' (following lines {linerange}  <a href="{url|urlescape}log/{
> symrev}/{file|urlescape}{sessionvars%urlparameter}">back to filelog</a>)'
> +)}</div>
>
>  <table>
>  {entries%filelogentry}
> diff --git a/tests/test-hgweb-filelog.t b/tests/test-hgweb-filelog.t
> --- a/tests/test-hgweb-filelog.t
> +++ b/tests/test-hgweb-filelog.t
> @@ -654,6 +654,219 @@ before addition - error
>
>    [1]
>
> +  $ hg log -r 'followlines(c, 1:2, startrev=tip) and follow(c)'
> +  changeset:   0:6563da9dcf87
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     b
> +
> +  changeset:   7:46c1a66bd8fc
> +  branch:      a-branch
> +  tag:         tip
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     change c
> +
> +  $ (get-with-headers.py localhost:$HGPORT 'log/tip/c?style=gitweb&
> linerange=1:2')
>

Can you please change one of these tests to percent encode the ':' as %3A,
as that is the proper URL encoding for colons? That could be done as a
follow-up.


> +  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: File revisions</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>  / file revisions
> +  </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/c?style=gitweb">file</a> |
> +  revisions |
> +  <a href="/annotate/tip/c?style=gitweb">annotate</a> |
> +  <a href="/diff/tip/c?style=gitweb">diff</a> |
> +  <a href="/comparison/tip/c?style=gitweb">comparison</a> |
> +  <a href="/rss-log/tip/c">rss</a> |
> +  <a href="/help?style=gitweb">help</a>
> +  <br/>
> +
> +  </div>
> +
> +  <div class="title">c (following lines 1:2  <a
> href="/log/tip/c?style=gitweb">back to filelog</a>)</div>
> +
> +  <table>
> +
> +  <tr class="parity1">
> +  <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
> +  <td><i>test</i></td>
> +  <td>
> +  <a class="list" href="/rev/46c1a66bd8fc?style=gitweb">
> +  <b>change c</b>
> +  <span class="logtags"><span class="branchtag"
> title="a-branch">a-branch</span> <span class="tagtag"
> title="tip">tip</span> </span>
> +  </a>
> +  </td>
> +  <td class="link">
> +  <a href="/file/46c1a66bd8fc/c?style=gitweb">file</a> |
> +  <a href="/diff/46c1a66bd8fc/c?style=gitweb">diff</a> |
> +  <a href="/annotate/46c1a66bd8fc/c?style=gitweb">annotate</a>
> +
> +  </td>
> +  </tr>
> +  <tr class="parity0">
> +  <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
> +  <td><i>test</i></td>
> +  <td>
> +  <a class="list" href="/rev/6563da9dcf87?style=gitweb">
> +  <b>b</b>
> +  <span class="logtags"></span>
> +  </a>
> +  </td>
> +  <td class="link">
> +  <a href="/file/6563da9dcf87/b?style=gitweb">file</a> |
> +  <a href="/diff/6563da9dcf87/b?style=gitweb">diff</a> |
> +  <a href="/annotate/6563da9dcf87/b?style=gitweb">annotate</a>
> +
> +  </td>
> +  </tr>
> +  </table>
> +
> +  <div class="page_nav">
> +  <a href="/log/tip/c?linerange=1%3A2&revcount=30&style=gitweb">less</a>
> +  <a href="/log/tip/c?linerange=1%3A2&revcount=120&style=gitweb">more</a>
> +
> +  </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 'log/tip/c?style=gitweb&
> linerange=1:2&revcount=1')
> +  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: File revisions</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>  / file revisions
> +  </div>
> +
> +  <div class="page_nav">
> +  <a href="/summary?revcount=1&style=gitweb">summary</a> |
> +  <a href="/shortlog?revcount=1&style=gitweb">shortlog</a> |
> +  <a href="/log?revcount=1&style=gitweb">changelog</a> |
> +  <a href="/graph?revcount=1&style=gitweb">graph</a> |
> +  <a href="/tags?revcount=1&style=gitweb">tags</a> |
> +  <a href="/bookmarks?revcount=1&style=gitweb">bookmarks</a> |
> +  <a href="/branches?revcount=1&style=gitweb">branches</a> |
> +  <a href="/file/tip/c?revcount=1&style=gitweb">file</a> |
> +  revisions |
> +  <a href="/annotate/tip/c?revcount=1&style=gitweb">annotate</a> |
> +  <a href="/diff/tip/c?revcount=1&style=gitweb">diff</a> |
> +  <a href="/comparison/tip/c?revcount=1&style=gitweb">comparison</a> |
> +  <a href="/rss-log/tip/c">rss</a> |
> +  <a href="/help?revcount=1&style=gitweb">help</a>
> +  <br/>
> +
> +  </div>
> +
> +  <div class="title">c (following lines 1:2  <a
> href="/log/tip/c?revcount=1&style=gitweb">back to filelog</a>)</div>
> +
> +  <table>
> +
> +  <tr class="parity0">
> +  <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
> +  <td><i>test</i></td>
> +  <td>
> +  <a class="list" href="/rev/46c1a66bd8fc?revcount=1&style=gitweb">
> +  <b>change c</b>
> +  <span class="logtags"><span class="branchtag"
> title="a-branch">a-branch</span> <span class="tagtag"
> title="tip">tip</span> </span>
> +  </a>
> +  </td>
> +  <td class="link">
> +  <a href="/file/46c1a66bd8fc/c?revcount=1&style=gitweb">file</a> |
> +  <a href="/diff/46c1a66bd8fc/c?revcount=1&style=gitweb">diff</a> |
> +  <a href="/annotate/46c1a66bd8fc/c?revcount=1&style=gitweb">annotate</a>
> +
> +  </td>
> +  </tr>
> +  </table>
> +
> +  <div class="page_nav">
> +  <a href="/log/tip/c?linerange=1%3A2&revcount=1&style=gitweb">less</a>
> +  <a href="/log/tip/c?linerange=1%3A2&revcount=2&style=gitweb">more</a>
> +
> +  </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 'log/3/a?linerange=1'
> --headeronly)
> +  400 invalid linerange parameter
> +  [1]
> +  $ (get-with-headers.py localhost:$HGPORT 'log/3/a?linerange=1:a'
> --headeronly)
> +  400 invalid linerange parameter
> +  [1]
> +  $ (get-with-headers.py localhost:$HGPORT 'log/3/a?linerange=1:2&linerange=3:4'
> --headeronly)
> +  400 redundant linerange parameter
> +  [1]
> +  $ (get-with-headers.py localhost:$HGPORT 'log/3/a?linerange=3:2'
> --headeronly)
> +  400 line range must be positive
> +  [1]
> +  $ (get-with-headers.py localhost:$HGPORT 'log/3/a?linerange=0:1'
> --headeronly)
> +  400 fromline must be strictly positive
> +  [1]
> +
>  should show base link, use spartan because it shows it
>
>    $ (get-with-headers.py localhost:$HGPORT 'log/tip/c?style=spartan')
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20170228/4eb33fb5/attachment.html>


More information about the Mercurial-devel mailing list