Mercurial > hg
changeset 20613:10433163bf57
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.
author | Durham Goode <durham@fb.com> |
---|---|
date | Sat, 16 Nov 2013 08:57:08 -0800 |
parents | 60c308b932eb |
children | 1bc68ff4e0a2 |
files | mercurial/revset.py tests/test-revset.t |
diffstat | 2 files changed, 38 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- 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