diff -r 9a2db13b2e99 -r dc247e648f43 hgext3rd/topic/revset.py --- a/hgext3rd/topic/revset.py Tue Aug 28 11:24:50 2018 +0200 +++ b/hgext3rd/topic/revset.py Mon Sep 03 22:05:12 2018 +0200 @@ -1,13 +1,13 @@ from __future__ import absolute_import from mercurial import ( + error, registrar, revset, util, ) from . import ( - constants, destination, stack, ) @@ -23,36 +23,64 @@ revsetpredicate = registrar.revsetpredicate() -@revsetpredicate('topic([topic])') -def topicset(repo, subset, x): - """Specified topic or all changes with any topic specified. +def getstringstrict(x, err): + if x and (x[0] == 'string'): + return x[1] + raise error.ParseError(err) - If `topic` starts with `re:` the remainder of the name is treated +@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. - - TODO: make `topic(revset)` work the same as `branch(revset)`. """ args = revset.getargs(x, 0, 1, 'topic takes one or no arguments') - if args: - # match a specific topic - topic = revset.getstring(args[0], 'topic() argument must be a string') - if topic == '.': - topic = repo['.'].extra().get('topic', '') - _kind, _pattern, matcher = mkmatcher(topic) - else: - matcher = lambda t: bool(t) mutable = revset._notpublic(repo, revset.fullreposet(repo), ()) - rawchange = repo.changelog.changelogrevision - key = constants.extrakey + if not args: + return (subset & mutable).filter(lambda r: bool(repo[r].topic())) + + try: + topic = getstringstrict(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 - def matchtopic(r): - topic = rawchange(r).extra.get(key) - if topic is None: + if pattern not in repo.topics and topic.startswith('literal:'): + raise error.RepoLookupError("topic '%s' does not exist" + % pattern) + return (subset & mutable).filter(matches) + 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 matcher(topic) - return (subset & mutable).filter(matchtopic) + return topic in topics + + return (subset & mutable).filter(matches) @revsetpredicate('ngtip([branch])') def ngtipset(repo, subset, x):