Mercurial > evolve
view hgext3rd/topic/revset.py @ 4061:ad4194399b47
topic: handle ambiguous arguments to topic() revset
These arguments can be interpreted as either string or a revset. The decision
is made based on existence of topic with such a name. This matches the behavior
of branch() revset.
The code needs to know all topics that ever existed in the repo, because some
commands report "disappearance" of topics after certain operations, using this
revset (e.g. via stack.stack or repo.revs).
author | Anton Shestakov <av6@dwimlabs.net> |
---|---|
date | Thu, 30 Aug 2018 21:05:17 +0800 |
parents | 54eade86ac31 |
children | 00c65abf99cd |
line wrap: on
line source
from __future__ import absolute_import from mercurial import ( error, registrar, revset, util, ) from . import ( destination, stack, ) try: mkmatcher = revset._stringmatcher except AttributeError: try: from mercurial.utils import stringutil mkmatcher = stringutil.stringmatcher except (ImportError, AttributeError): mkmatcher = util.stringmatcher revsetpredicate = registrar.revsetpredicate() @revsetpredicate('topic([string or set])') def topicset(repo, subset, x): """All changesets with the specified topic or the topics of the given changesets. Without the argument, all changesets with any topic specified. If `string` starts with `re:` the remainder of the name is treated as a regular expression. """ args = revset.getargs(x, 0, 1, 'topic takes one or no arguments') mutable = revset._notpublic(repo, revset.fullreposet(repo), ()) if not args: return (subset & mutable).filter(lambda r: bool(repo[r].topic())) try: topic = revset.getstring(args[0], '') except error.ParseError: # not a string, but another revset pass else: kind, pattern, matcher = mkmatcher(topic) def matches(r): topic = repo[r].topic() if not topic: return False return matcher(topic) if kind == 'literal': # note: falls through to the revset case if no topic with this name # exists and pattern kind is not specified explicitly alltopics = set([repo.currenttopic]) for r in repo.unfiltered().set('all()'): alltopics.add(r.topic(force=True)) alltopics.discard('') if pattern in alltopics: return (subset & mutable).filter(matches) if topic.startswith('literal:'): raise error.RepoLookupError("topic '%s' does not exist" % pattern) else: return (subset & mutable).filter(matches) s = revset.getset(repo, revset.fullreposet(repo), x) topics = set(repo[r].topic() for r in s) topics.discard('') def matches(r): if r in s: return True topic = repo[r].topic() if not topic: return False return topic in topics return (subset & mutable).filter(matches) @revsetpredicate('ngtip([branch])') def ngtipset(repo, subset, x): """The untopiced tip. Name is horrible so that people change it. """ args = revset.getargs(x, 1, 1, 'topic takes one') # match a specific topic branch = revset.getstring(args[0], 'ngtip() argument must be a string') if branch == '.': branch = repo['.'].branch() return subset & revset.baseset(destination.ngtip(repo, branch)) @revsetpredicate('stack()') def stackset(repo, subset, x): """All relevant changes in the current topic, This is roughly equivalent to 'topic(.) - obsolete' with a sorting moving unstable changeset after there future parent (as if evolve where already run).""" err = 'stack() takes no argument, it works on current topic' revset.getargs(x, 0, 0, err) topic = None branch = None if repo.currenttopic: topic = repo.currenttopic else: branch = repo[None].branch() return revset.baseset(stack.stack(repo, branch=branch, topic=topic)[1:]) & subset