pushlog: add pushid(N) and pushrev(set) revsets (bug 1295780); r?glandium draft
authorGregory Szorc <gps@mozilla.com>
Tue, 16 Aug 2016 15:42:34 -0700
changeset 9298 180537ad5fe1f0a616f89b63bbfceef2ef8ea76b
parent 9294 e094f8ce0682efa033eb936f5c1fe284099f96a5
push id1125
push userbmo:gps@mozilla.com
push dateThu, 25 Aug 2016 23:59:31 +0000
reviewersglandium
bugs1295780
pushlog: add pushid(N) and pushrev(set) revsets (bug 1295780); r?glandium We add support for querying for changesets based on their push id (find changesets in push X) and for changesets in the same push as a changeset. MozReview-Commit-ID: 33s1zUtg7SH
hgext/pushlog/__init__.py
hgext/pushlog/tests/test-revset.t
--- a/hgext/pushlog/__init__.py
+++ b/hgext/pushlog/__init__.py
@@ -625,16 +625,56 @@ def revset_pushuser(repo, subset, x):
     def getrevs():
         for push in repo.pushlog.pushes():
             if matcher(encoding.lower(push.user)):
                 for node in push.nodes:
                     yield repo[node].rev()
 
     return subset & revset.generatorset(getrevs())
 
+@revsetpredicate('pushid(int)')
+def revset_pushid(repo, subset, x):
+    """Changesets that were part of the specified numeric push id."""
+    l = revset.getargs(x, 1, 1, 'pushid requires one argument')
+    try:
+        pushid = int(revset.getstring(l[0], 'pushid requires a number'))
+    except (TypeError, ValueError):
+        raise error.ParseError('pushid expects a number')
+
+    with repo.pushlog.conn(readonly=True) as conn:
+        push = repo.pushlog.pushfromid(conn, pushid) if conn else None
+
+    if not push:
+        return revset.baseset()
+
+    pushrevs = set()
+    for node in push.nodes:
+        try:
+            pushrevs.add(repo[node].rev())
+        except RepoLookupError:
+            pass
+
+    return subset & pushrevs
+
+@revsetpredicate('pushrev(set)')
+def revset_pushrev(repo, subset, x):
+    """Changesets that were part of the same push as the specified changeset(s)."""
+    l = revset.getset(repo, subset, x)
+
+    # This isn't the most optimal implementation, especially if the input
+    # set is large. But it gets the job done.
+    revs = set()
+    for rev in l:
+        push = repo.pushlog.pushfromchangeset(repo[rev])
+        if push:
+            for node in push.nodes:
+                revs.add(repo[node].rev())
+
+    return subset.filter(revs.__contains__)
+
 # Again, for performance reasons we read the entire pushlog database and cache
 # the results. Again, this is unfortunate. But, the alternative is a potential
 # very expensive series of database lookups.
 #
 # The justification for doing this for templates is even less than doing it for
 # revsets because where revsets typically need to operate on lots of
 # changesets, templates typically only render a small handful of changesets.
 # Performing a query for each changeset being templatized is an easier pill to
--- a/hgext/pushlog/tests/test-revset.t
+++ b/hgext/pushlog/tests/test-revset.t
@@ -86,8 +86,64 @@ pushuser() does regex matching
   $ hg log -r 'pushuser("re:user1")' -T '{rev}\n'
   0
 
 pushuser() matching is case insensitive
 
   $ hg log -r 'pushuser(user2@EXAMPLE.COM)' -T '{rev}\n'
   1
   2
+
+pushid() requires an argument
+
+  $ hg log -r 'pushid()'
+  hg: parse error: pushid requires one argument
+  [255]
+
+pushid() requires an integer argument
+
+  $ hg log -r 'pushid("foo")'
+  hg: parse error: pushid expects a number
+  [255]
+
+pushid() returns revisions part of the specified push
+
+  $ hg log -r 'pushid(1)' -T '{rev}\n'
+  0
+  $ hg log -r 'pushid(2)' -T '{rev}\n'
+  1
+  2
+
+pushid() works with unknown pushid values
+
+  $ hg log -r 'pushid(3)' -T '{rev}\n'
+
+pushid() set intersection works
+
+  $ hg log -r '6c9721b3b4df & pushid(2)' -T '{rev}\n'
+  1
+
+pushrev() returns an empty set by default
+
+  $ hg log -r 'pushrev()'
+  hg: parse error: missing argument
+  [255]
+
+pushrev() returns values for single revision
+
+  $ hg log -r 'pushrev(55482a6fb4b1)' -T '{rev}\n'
+  0
+
+  $ hg log -r 'pushrev(6c9721b3b4df)' -T '{rev}\n'
+  1
+  2
+
+pushrev() returns values for multiple revisions
+
+  $ hg log -r 'pushrev(0:tip)' -T '{rev}\n'
+  0
+  1
+  2
+
+pushrev() set intersection works
+
+  $ hg log -r '6c9721b3b4df & pushrev(1)' -T '{rev}\n'
+  1