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,