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.
--- a/mercurial/revset.py Mon Jan 09 16:55:56 2017 +0900
+++ b/mercurial/revset.py Mon Jan 09 17:58:19 2017 +0900
@@ -329,6 +329,20 @@
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 @@
# 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 @@
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 @@
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:
--- a/tests/test-annotate.t Mon Jan 09 16:55:56 2017 +0900
+++ b/tests/test-annotate.t Mon Jan 09 17:58:19 2017 +0900
@@ -486,43 +486,43 @@
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 @@
$ 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 @@
$ 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 @@
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 @@
(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 @@
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, :1)'
hg: parse error: line range bounds must be integers
[255]
- $ hg log -r 'followlines(baz, 5, 4)'
+ $ 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]