diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -815,6 +815,45 @@ contentdivergent = obsmod.getrevs(repo, 'contentdivergent') return subset & contentdivergent +@predicate('expectsize(set[, size])', safe=True, takeorder=True) +def expectrevsetsize(repo, subset, x, order): + """Abort if the revset doesn't expect given size""" + args = getargsdict(x, 'expect', 'set size') + size = args.get('size') + if size is not None: + minsize, maxsize = getintrange(size, + _('expectsize requires a size range' + ' or a positive integer'), + _('size range bounds must be integers')) + if minsize < 0 or maxsize < 0: + raise error.ParseError(_('negative size')) + if minsize != maxsize: + size = (minsize, maxsize) + else: + size = minsize + if size is None or 'set' not in args: + raise error.ParseError(_('invalid set of arguments')) + rev = getset(repo, fullreposet(repo), args['set'], order=order) + if isinstance(size, tuple): + if len(rev) < minsize or len(rev) > maxsize: + raise error.RepoLookupError( + _('revset size mismatch.' + ' expected between %d and %d, got %d') % (minsize, + maxsize, + len(rev))) + if isinstance(size, int): + if len(rev) != size: + raise error.RepoLookupError( + _('revset size mismatch.' + ' expected %d, got %d') % (size, len(rev))) + # filter rev by subset. since we'll probably want to get an ordered + # result from expectsize(), we'll have to conditionalize the + # filtering direction + if order == followorder: + return subset & rev + else: + return rev & subset + @predicate('extdata(source)', safe=False, weight=100) def extdata(repo, subset, x): """Changesets in the specified extdata source. (EXPERIMENTAL)""" diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -2950,3 +2950,45 @@ * set: 0 + +abort if the revset doesn't expect given size + $ log 'expectsize()' + hg: parse error: invalid set of arguments + [255] + $ log 'expectsize(0:2, a)' + hg: parse error: expectsize requires a size range or a positive integer + [255] + $ log 'expectsize(0:2, 3)' + 0 + 1 + 2 + + $ log 'expectsize(2:0, 3)' + 2 + 1 + 0 + $ log 'expectsize(0:1, 1)' + abort: revset size mismatch. expected 1, got 2! + [255] + $ log 'expectsize(0:4, -1)' + hg: parse error: negative size + [255] + $ log 'expectsize(0:2, 2:4)' + 0 + 1 + 2 + $ log 'expectsize(0:1, 3:5)' + abort: revset size mismatch. expected between 3 and 5, got 2! + [255] + $ log 'expectsize(0:1, -1:2)' + hg: parse error: negative size + [255] + $ log 'expectsize(0:1, 1:-2)' + hg: parse error: negative size + [255] + $ log 'expectsize(0:2, a:4)' + hg: parse error: size range bounds must be integers + [255] + $ log 'expectsize(0:2, 2:b)' + hg: parse error: size range bounds must be integers + [255]