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.
--- a/mercurial/revset.py Thu Feb 06 17:42:08 2014 -0800
+++ b/mercurial/revset.py Sat Nov 16 08:57:08 2013 -0800
@@ -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,26 @@
kind, pattern, matcher = _substringmatcher(n)
return subset.filter(lambda x: matcher(encoding.lower(repo[x].user())))
+def only(repo, subset, x):
+ """``only(set, [set])``
+ Changesets that are ancestors of the first set that are not ancestors
+ of any other head in the repo. If a second set is specified, the result
+ is ancestors of the first set that are not ancestors of the second set
+ (i.e. ::<set1> - ::<set2>).
+ """
+ cl = repo.changelog
+ args = getargs(x, 1, 2, _('only takes one or two arguments'))
+ include = getset(repo, spanset(repo), args[0]).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, spanset(repo), 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:
@@ -1606,6 +1627,7 @@
"ancestors": ancestors,
"_firstancestors": _firstancestors,
"author": author,
+ "only": only,
"bisect": bisect,
"bisected": bisected,
"bookmark": bookmark,
--- a/tests/test-revset.t Thu Feb 06 17:42:08 2014 -0800
+++ b/tests/test-revset.t Sat Nov 16 08:57:08 2013 -0800
@@ -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