Patchwork [3,of,3] revset: add optional offset argument to limit() predicate

login
register
mail settings
Submitter Yuya Nishihara
Date Oct. 13, 2015, 3:57 p.m.
Message ID <237fcd04a19307260b21.1444751846@mimosa>
Download mbox | patch
Permalink /patch/11009/
State Accepted
Headers show

Comments

Yuya Nishihara - Oct. 13, 2015, 3:57 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1427124508 -32400
#      Tue Mar 24 00:28:28 2015 +0900
# Node ID 237fcd04a19307260b211019046fc6d2945221da
# Parent  5da62cb1c7370d0da4d0e28aaa7a2e423cd43cf6
revset: add optional offset argument to limit() predicate

It's common for GUI or web frontend to fetch chunk of revisions per batch
size. Previously it was possible only if revisions were sorted by revision
number.

  $ hg log -r 'limit({revspec} & :{last_known}, 101)'

So this patch introduces a general way to retrieve chunk of revisions after
skipping offset revisions.

  $ hg log -r 'limit({revspec}, 100, {last_count})'

This is a dumb implementation. We can optimize it for baseset and spanset
later.
Pierre-Yves David - Oct. 14, 2015, 4:16 a.m.
On 10/13/2015 08:57 AM, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1427124508 -32400
> #      Tue Mar 24 00:28:28 2015 +0900
> # Node ID 237fcd04a19307260b211019046fc6d2945221da
> # Parent  5da62cb1c7370d0da4d0e28aaa7a2e423cd43cf6
> revset: add optional offset argument to limit() predicate

Nice, pushed to the clowncopter

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -1284,24 +1284,33 @@  def keyword(repo, subset, x):
     return subset.filter(matches)
 
 def limit(repo, subset, x):
-    """``limit(set, [n])``
-    First n members of set, defaulting to 1.
+    """``limit(set[, n[, offset]])``
+    First n members of set, defaulting to 1, starting from offset.
     """
-    args = getargsdict(x, 'limit', 'set n')
+    args = getargsdict(x, 'limit', 'set n offset')
     if 'set' not in args:
         # i18n: "limit" is a keyword
-        raise error.ParseError(_("limit requires one or two arguments"))
+        raise error.ParseError(_("limit requires one to three arguments"))
     try:
-        lim = 1
+        lim, ofs = 1, 0
         if 'n' in args:
             # i18n: "limit" is a keyword
             lim = int(getstring(args['n'], _("limit requires a number")))
+        if 'offset' in args:
+            # i18n: "limit" is a keyword
+            ofs = int(getstring(args['offset'], _("limit requires a number")))
+        if ofs < 0:
+            raise error.ParseError(_("negative offset"))
     except (TypeError, ValueError):
         # i18n: "limit" is a keyword
         raise error.ParseError(_("limit expects a number"))
     os = getset(repo, fullreposet(repo), args['set'])
     result = []
     it = iter(os)
+    for x in xrange(ofs):
+        y = next(it, None)
+        if y is None:
+            break
     for x in xrange(lim):
         y = next(it, None)
         if y is None:
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -566,6 +566,16 @@  test ancestors
   $ log 'keyword("test a")'
   $ log 'limit(head(), 1)'
   0
+  $ log 'limit(author("re:bob|test"), 3, 5)'
+  5
+  6
+  7
+  $ log 'limit(author("re:bob|test"), offset=6)'
+  6
+  $ log 'limit(author("re:bob|test"), offset=10)'
+  $ log 'limit(all(), 1, -1)'
+  hg: parse error: negative offset
+  [255]
   $ log 'matching(6)'
   6
   $ log 'matching(6:7, "phase parents user date branch summary files description substate")'