[PATCH] revset: add 'only' revset

Lucas Moscovicz lmoscovicz at fb.com
Thu Feb 27 12:37:09 CST 2014



On 2/26/14, 11:35 AM, "Durham Goode" <durham at fb.com> wrote:

># HG changeset patch
># User Durham Goode <durham at fb.com>
># Date 1384621028 28800
>#      Sat Nov 16 08:57:08 2013 -0800
># Node ID 9bcbd10a93137b4dbc83bebd41fb4f00143a7615
># Parent  0ad353831461516132f57ccda8e8e0515213ec60
>revset: add 'only' revset
>
>Adds a only() revset that has two forms:
>
>only(<set>) is equivalent to "::<set> - ::(heads() - heads(<set>::))"
>
>only(<include>,<exclude>) is equivalent to "::<include> - ::<exclude>"
>
>On a large repo, this implementation can process/traverse 50,000 revs in
>0.7
>seconds, versus 4.2 seconds using "::<include> - ::<exclude>".
>
>This is useful for performing histedits on your branch:
>hg histedit -r 'first(only(.))'
>
>Or lifting branch foo off of branch bar:
>hg rebase -d @ -s 'only(foo, bar)'
>
>Or a variety of other uses.
>
>diff --git a/mercurial/revset.py b/mercurial/revset.py
>--- a/mercurial/revset.py
>+++ b/mercurial/revset.py
>@@ -9,6 +9,7 @@
> import parser, util, error, discovery, hbisect, phases
> import node
> import match as matchmod
>+import ancestor as ancestormod
> from i18n import _
> import encoding
> import obsolete as obsmod
>@@ -351,6 +352,25 @@
>     kind, pattern, matcher = _substringmatcher(n)
>     return lazyset(subset, lambda x:
>matcher(encoding.lower(repo[x].user())))
> 
>+def only(repo, subset, x):
>+    """``only(set, [set])
>+    Changesets that are only ancestors of the first set, but not the
>second.
>+    If no second set is specified, it is assumed to be the heads that are
>+    not in or descendants of the first set.
>+    """
>+    cl = repo.changelog
>+    args = getargs(x, 1, 2, _('only takes one or two arguments'))
>+    include = set(getset(repo, baseset(cl), args[0]))

Here you should use getset(repo, baseset(cl), args[0]).set() since
anything returned by getset should have that method at this point and in
many cases it will be more efficient (when it¹s a spanset for example
it¹ll just return itself since it¹s contains is fast instead of going
through all the values to build a set)

>+    if len(args) == 1:
>+        descendants = set(_revdescendants(repo, include, False))
>+        exclude = [rev for rev in cl.headrevs()
>+            if not rev in descendants and not rev in include]
>+    else:
>+        exclude = getset(repo, baseset(cl), args[1])
>+
>+    results = set(ancestormod.missingancestors(include, exclude,
>cl.parentrevs))
>+    return lazyset(subset, lambda x: x in results)
>+
> def bisect(repo, subset, x):
>     """``bisect(string)``
>     Changesets marked in the specified bisect status:
>@@ -1587,6 +1607,7 @@
>     "ancestors": ancestors,
>     "_firstancestors": _firstancestors,
>     "author": author,
>+    "only": only,
>     "bisect": bisect,
>     "bisected": bisected,
>     "bookmark": bookmark,
>diff --git a/tests/test-revset.t b/tests/test-revset.t
>--- a/tests/test-revset.t
>+++ b/tests/test-revset.t
>@@ -367,6 +367,22 @@
>   4
>   $ log 'id(5)'
>   2
>+  $ log 'only(9)'
>+  8
>+  9
>+  $ log 'only(8)'
>+  8
>+  $ log 'only(9, 5)'
>+  2
>+  4
>+  8
>+  9
>+  $ log 'only(7 + 9, 5 + 2)'
>+  4
>+  6
>+  7
>+  8
>+  9
>   $ log 'outgoing()'
>   8
>   9
>_______________________________________________
>Mercurial-devel mailing list
>Mercurial-devel at selenic.com
>https://urldefense.proofpoint.com/v1/url?u=http://selenic.com/mailman/list
>info/mercurial-devel&k=ZVNjlDMF0FElm4dQtryO4A%3D%3D%0A&r=OvJpSDyvbZ%2BdRIG
>uE%2BQNXdEMu%2FMWX%2BVvreTVxvKUMnE%3D%0A&m=9HUK%2FsgHAMmXj9vn9d7PymqiQsJ4u
>KxSQcakrrGrIvs%3D%0A&s=7c65d79c34da7f3b293578f7330bfbff9814de6fd83ee718c84
>a39913c4d6270



More information about the Mercurial-devel mailing list