1065 def _followfirst(repo, subset, x): |
1065 def _followfirst(repo, subset, x): |
1066 # ``followfirst([pattern[, startrev]])`` |
1066 # ``followfirst([pattern[, startrev]])`` |
1067 # Like ``follow([pattern[, startrev]])`` but follows only the first parent |
1067 # Like ``follow([pattern[, startrev]])`` but follows only the first parent |
1068 # of every revisions or files revisions. |
1068 # of every revisions or files revisions. |
1069 return _follow(repo, subset, x, '_followfirst', followfirst=True) |
1069 return _follow(repo, subset, x, '_followfirst', followfirst=True) |
|
1070 |
|
1071 @predicate('followlines(file, fromline, toline[, rev=.])', safe=True) |
|
1072 def followlines(repo, subset, x): |
|
1073 """Changesets modifying `file` in line range ('fromline', 'toline'). |
|
1074 |
|
1075 Line range corresponds to 'file' content at 'rev' and should hence be |
|
1076 consistent with file size. If rev is not specified, working directory's |
|
1077 parent is used. |
|
1078 """ |
|
1079 from . import context # avoid circular import issues |
|
1080 |
|
1081 args = getargs(x, 3, 4, _("followlines takes at least three arguments")) |
|
1082 |
|
1083 rev = '.' |
|
1084 if len(args) == 4: |
|
1085 revarg = getargsdict(args[3], 'followlines', 'rev') |
|
1086 if 'rev' in revarg: |
|
1087 revs = getset(repo, fullreposet(repo), revarg['rev']) |
|
1088 if len(revs) != 1: |
|
1089 raise error.ParseError( |
|
1090 _("followlines expects exactly one revision")) |
|
1091 rev = revs.last() |
|
1092 |
|
1093 pat = getstring(args[0], _("followlines requires a pattern")) |
|
1094 if not matchmod.patkind(pat): |
|
1095 fname = pathutil.canonpath(repo.root, repo.getcwd(), pat) |
|
1096 else: |
|
1097 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[rev]) |
|
1098 files = [f for f in repo[rev] if m(f)] |
|
1099 if len(files) != 1: |
|
1100 raise error.ParseError(_("followlines expects exactly one file")) |
|
1101 fname = files[0] |
|
1102 |
|
1103 try: |
|
1104 fromline, toline = [int(getsymbol(a)) for a in args[1:3]] |
|
1105 except ValueError: |
|
1106 raise error.ParseError(_("line range bounds must be integers")) |
|
1107 if toline - fromline < 0: |
|
1108 raise error.ParseError(_("line range must be positive")) |
|
1109 if fromline < 1: |
|
1110 raise error.ParseError(_("fromline must be strictly positive")) |
|
1111 fromline -= 1 |
|
1112 |
|
1113 fctx = repo[rev].filectx(fname) |
|
1114 revs = (c.rev() for c in context.blockancestors(fctx, fromline, toline)) |
|
1115 return subset & generatorset(revs, iterasc=False) |
1070 |
1116 |
1071 @predicate('all()', safe=True) |
1117 @predicate('all()', safe=True) |
1072 def getall(repo, subset, x): |
1118 def getall(repo, subset, x): |
1073 """All changesets, the same as ``0:tip``. |
1119 """All changesets, the same as ``0:tip``. |
1074 """ |
1120 """ |