# HG changeset patch # User Denis Laxalde # Date 2017-01-19 16:41:00 # Node ID 5e6d44511317363a6e90c12fc24e2ecab338911f # Parent 1cbeefa5934359a900c6a50240bcb0831c08a934 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//?linerange=: 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 update the "paper" template in this patch. 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, @@ -968,6 +969,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']) @@ -996,24 +999,49 @@ def filelog(web, req, tmpl): path = fctx.path() return webutil.diffs(web, tmpl, ctx, basectx, [path], diffstyle) - for i in revs: - iterfctx = fctx.filectx(i) - diffs = None - if patch: - diffs = diff(iterfctx) - entries.append(dict( - parity=next(parity), - filerev=i, - file=f, - diff=diffs, - 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): + diffs = None + if patch: + diffs = diff(c) + # follow renames accross filtered (not in range) revisions + path = c.path() + entries.append(dict( + parity=next(parity), + filerev=c.rev(), + file=path, + diff=diffs, + 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) + diffs = None + if patch: + diffs = diff(iterfctx) + entries.append(dict( + parity=next(parity), + filerev=i, + file=f, + diff=diffs, + 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, @@ -1021,6 +1049,7 @@ def filelog(web, req, tmpl): entries=entries, patch=patch, 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, ) @@ -317,6 +318,26 @@ 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: + fromline, toline = map(int, linerange[0].split(':', 1)) + except ValueError: + raise ErrorResponse(HTTP_BAD_REQUEST, + 'invalid linerange parameter') + try: + return util.processlinerange(fromline, toline) + except error.ParseError 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/paper/filelog.tmpl b/mercurial/templates/paper/filelog.tmpl --- a/mercurial/templates/paper/filelog.tmpl +++ b/mercurial/templates/paper/filelog.tmpl @@ -47,6 +47,8 @@

log {file|escape} @ {rev}:{node|short} {branch%changelogbranchname}{tags%changelogtag}{bookmarks%changelogtag} + {if(linerange, +' (following lines {linerange} back to filelog)')}

+ + + + + + + $ (get-with-headers.py localhost:$HGPORT 'log/tip/c?linerange=1%3A2&revcount=1') + 200 Script output follows + + + + + + + + + + test: c history + + + + + +
+ + +
+ +

+ log c @ 7:46c1a66bd8fc + a-branch tip + (following lines 1:2 back to filelog) +

+ + + + + + + + + + + + + + + + + + + + + + +
ageauthordescription
Thu, 01 Jan 1970 00:00:00 +0000test + change c + a-branch tip +
+ + + +
+
+ + + + + + + $ (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') @@ -829,6 +1091,7 @@ filelog with patch

log a @ 4:3f41bc784e7e a-branch +