revset: abuse x:y syntax to specify line range of followlines()

This slightly complicates the parsing (see the previous patch), but the
overall result seems not bad.

I keep x:, :y and : for future extension.
This commit is contained in:
Yuya Nishihara 2017-01-09 17:58:19 +09:00
parent 615f3c1669
commit 5ade140d5c
2 changed files with 45 additions and 24 deletions

View File

@ -329,6 +329,20 @@ def getlist(x):
return list(x[1:])
return [x]
def getrange(x, err):
if not x:
raise error.ParseError(err)
op = x[0]
if op == 'range':
return x[1], x[2]
elif op == 'rangepre':
return None, x[1]
elif op == 'rangepost':
return x[1], None
elif op == 'rangeall':
return None, None
raise error.ParseError(err)
def getargs(x, min, max, err):
l = getlist(x)
if len(l) < min or (max >= 0 and len(l) > max):
@ -1083,7 +1097,7 @@ def _followfirst(repo, subset, x):
# of every revisions or files revisions.
return _follow(repo, subset, x, '_followfirst', followfirst=True)
@predicate('followlines(file, fromline, toline[, startrev=.])', safe=True)
@predicate('followlines(file, fromline:toline[, startrev=.])', safe=True)
def followlines(repo, subset, x):
"""Changesets modifying `file` in line range ('fromline', 'toline').
@ -1094,8 +1108,8 @@ def followlines(repo, subset, x):
from . import context # avoid circular import issues
args = getargsdict(x, 'followlines', 'file *lines startrev')
if len(args['lines']) != 2:
raise error.ParseError(_("followlines takes at least three arguments"))
if len(args['lines']) != 1:
raise error.ParseError(_("followlines requires a line range"))
rev = '.'
if 'startrev' in args:
@ -1115,8 +1129,9 @@ def followlines(repo, subset, x):
raise error.ParseError(_("followlines expects exactly one file"))
fname = files[0]
lr = getrange(args['lines'][0], _("followlines expects a line range"))
fromline, toline = [getinteger(a, _("line range bounds must be integers"))
for a in args['lines']]
for a in lr]
if toline - fromline < 0:
raise error.ParseError(_("line range must be positive"))
if fromline < 1:

View File

@ -486,43 +486,43 @@ annotate removed file
Test followlines() revset
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3, 5)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5)'
16: baz:0
19: baz:3
20: baz:4
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3, 5, startrev=20)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, startrev=20)'
16: baz:0
19: baz:3
20: baz:4
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3, 5, startrev=.^)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, startrev=.^)'
16: baz:0
19: baz:3
$ printf "0\n0\n" | cat - baz > baz1
$ mv baz1 baz
$ hg ci -m 'added two lines with 0'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5, 7)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7)'
16: baz:0
19: baz:3
20: baz:4
$ echo 6 >> baz
$ hg ci -m 'added line 8'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5, 7)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7)'
16: baz:0
19: baz:3
20: baz:4
$ sed 's/3/3+/' baz > baz.new
$ mv baz.new baz
$ hg ci -m 'baz:3->3+'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5, 7)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7)'
16: baz:0
19: baz:3
20: baz:4
23: baz:3->3+
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 1, 2)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 1:2)'
21: added two lines with 0
file patterns are okay
$ hg log -T '{rev}: {desc}\n' -r 'followlines("path:baz", 1, 2)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines("path:baz", 1:2)'
21: added two lines with 0
renames are followed
@ -530,7 +530,7 @@ renames are followed
$ sed 's/4/4+/' qux > qux.new
$ mv qux.new qux
$ hg ci -m 'qux:4->4+'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5, 7)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5:7)'
16: baz:0
19: baz:3
20: baz:4
@ -545,7 +545,7 @@ merge
$ sed 's/3+/3-/' baz > baz.new
$ mv baz.new baz
$ hg ci -m 'baz:3+->3-'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5, 7)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7)'
16: baz:0
19: baz:3
20: baz:4
@ -556,7 +556,7 @@ merge
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg ci -m merge
$ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5, 7)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5:7)'
16: baz:0
19: baz:3
20: baz:4
@ -571,7 +571,7 @@ merge
(branch merge, don't forget to commit)
$ hg ci -m 'merge from other side'
created new head
$ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5, 7)'
$ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5:7)'
16: baz:0
19: baz:3
20: baz:4
@ -586,27 +586,33 @@ check error cases
hg: parse error: followlines takes at least 1 positional arguments
[255]
$ hg log -r 'followlines(baz)'
hg: parse error: followlines takes at least three arguments
hg: parse error: followlines requires a line range
[255]
$ hg log -r 'followlines(baz, 1)'
hg: parse error: followlines takes at least three arguments
hg: parse error: followlines expects a line range
[255]
$ hg log -r 'followlines(baz, 1, 2, startrev=desc("b"))'
$ hg log -r 'followlines(baz, 1:2, startrev=desc("b"))'
hg: parse error: followlines expects exactly one revision
[255]
$ hg log -r 'followlines("glob:*", 1, 2)'
$ hg log -r 'followlines("glob:*", 1:2)'
hg: parse error: followlines expects exactly one file
[255]
$ hg log -r 'followlines(baz, x, 4)'
$ hg log -r 'followlines(baz, 1:)'
hg: parse error: line range bounds must be integers
[255]
$ hg log -r 'followlines(baz, 5, 4)'
$ hg log -r 'followlines(baz, :1)'
hg: parse error: line range bounds must be integers
[255]
$ hg log -r 'followlines(baz, x:4)'
hg: parse error: line range bounds must be integers
[255]
$ hg log -r 'followlines(baz, 5:4)'
hg: parse error: line range must be positive
[255]
$ hg log -r 'followlines(baz, 0, 4)'
$ hg log -r 'followlines(baz, 0:4)'
hg: parse error: fromline must be strictly positive
[255]
$ hg log -r 'followlines(baz, 2, 40)'
$ hg log -r 'followlines(baz, 2:40)'
abort: line range exceeds file size
[255]