Mercurial > public > mercurial-scm > hg
comparison mercurial/revset.py @ 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 | f2bb7ba59456 |
comparison
equal
deleted
inserted
replaced
20612:60c308b932eb | 20613:10433163bf57 |
---|---|
7 | 7 |
8 import re | 8 import re |
9 import parser, util, error, discovery, hbisect, phases | 9 import parser, util, error, discovery, hbisect, phases |
10 import node | 10 import node |
11 import match as matchmod | 11 import match as matchmod |
12 import ancestor as ancestormod | |
12 from i18n import _ | 13 from i18n import _ |
13 import encoding | 14 import encoding |
14 import obsolete as obsmod | 15 import obsolete as obsmod |
15 import pathutil | 16 import pathutil |
16 import repoview | 17 import repoview |
349 # i18n: "author" is a keyword | 350 # i18n: "author" is a keyword |
350 n = encoding.lower(getstring(x, _("author requires a string"))) | 351 n = encoding.lower(getstring(x, _("author requires a string"))) |
351 kind, pattern, matcher = _substringmatcher(n) | 352 kind, pattern, matcher = _substringmatcher(n) |
352 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user()))) | 353 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user()))) |
353 | 354 |
355 def only(repo, subset, x): | |
356 """``only(set, [set])`` | |
357 Changesets that are ancestors of the first set that are not ancestors | |
358 of any other head in the repo. If a second set is specified, the result | |
359 is ancestors of the first set that are not ancestors of the second set | |
360 (i.e. ::<set1> - ::<set2>). | |
361 """ | |
362 cl = repo.changelog | |
363 args = getargs(x, 1, 2, _('only takes one or two arguments')) | |
364 include = getset(repo, spanset(repo), args[0]).set() | |
365 if len(args) == 1: | |
366 descendants = set(_revdescendants(repo, include, False)) | |
367 exclude = [rev for rev in cl.headrevs() | |
368 if not rev in descendants and not rev in include] | |
369 else: | |
370 exclude = getset(repo, spanset(repo), args[1]) | |
371 | |
372 results = set(ancestormod.missingancestors(include, exclude, cl.parentrevs)) | |
373 return lazyset(subset, lambda x: x in results) | |
374 | |
354 def bisect(repo, subset, x): | 375 def bisect(repo, subset, x): |
355 """``bisect(string)`` | 376 """``bisect(string)`` |
356 Changesets marked in the specified bisect status: | 377 Changesets marked in the specified bisect status: |
357 | 378 |
358 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip | 379 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip |
1604 "all": getall, | 1625 "all": getall, |
1605 "ancestor": ancestor, | 1626 "ancestor": ancestor, |
1606 "ancestors": ancestors, | 1627 "ancestors": ancestors, |
1607 "_firstancestors": _firstancestors, | 1628 "_firstancestors": _firstancestors, |
1608 "author": author, | 1629 "author": author, |
1630 "only": only, | |
1609 "bisect": bisect, | 1631 "bisect": bisect, |
1610 "bisected": bisected, | 1632 "bisected": bisected, |
1611 "bookmark": bookmark, | 1633 "bookmark": bookmark, |
1612 "branch": branch, | 1634 "branch": branch, |
1613 "branchpoint": branchpoint, | 1635 "branchpoint": branchpoint, |