src/topic/__init__.py
author Augie Fackler <augie@google.com>
Wed, 10 Jun 2015 14:59:05 -0400
changeset 1840 2321fd2ed56e
parent 1839 1bc5e62fc0c7
child 1841 72a58a5bfb62
permissions -rw-r--r--
testlib: enable rebase and obsolete for easier testing

# __init__.py - topic extension
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""Adds topic branches. Topic branches are lightweight branches which
dissappear when changes are finalized.

This is sort of similar to a bookmark, but it applies to a whole
series instead of a single revision.
"""
import functools

from mercurial import cmdutil
from mercurial import commands
from mercurial import extensions
from mercurial import namespaces
from mercurial import phases
from mercurial import util

cmdtable = {}
command = cmdutil.command(cmdtable)

def _namemap(repo, name):
    return [ctx.node() for ctx in
            repo.set('not public() and extra(topic, %s)', name)]

def _nodemap(repo, node):
    ctx = repo[node]
    t = ctx.extra().get('topic', '')
    if t and ctx.phase() > phases.public:
        return [t]
    return []

def reposetup(ui, repo):
    orig = repo.__class__
    class topicrepo(repo.__class__):
        def commitctx(self, ctx, error=None):
            current = self.currenttopic
            if current:
                ctx.extra()['topic'] = current
            return orig.commitctx(self, ctx, error=error)

        @property
        def topics(self):
            topics = set(['', self.currenttopic])
            for rev in self.revs('not public()'):
                c = self.changectx(rev)
                topics.add(c.extra().get('topic', ''))
            topics.remove('')
            return topics

        @property
        def currenttopic(self):
            return self.vfs.tryread('topic')

    if util.safehasattr(repo, 'names'):
        repo.names.addnamespace(namespaces.namespace(
            'topics', 'topic', namemap=_namemap, nodemap=_nodemap))
    repo.__class__ = topicrepo

@command('topics', [
    ('', 'clear', False, 'clear active topic if any'),
])
def topics(ui, repo, topic=None, clear=False):
    """View current topic, set current topic, or see all topics."""
    if clear:
        if repo.vfs.exists('topic'):
            repo.vfs.unlink('topic')
        return
    if topic is not None:
        with repo.vfs.open('topic', 'w') as f:
            f.write(topic)
        return
    current = repo.currenttopic
    for t in sorted(repo.topics):
        marker = '*' if t == current else ' '
        ui.write(' %s %s\n' % (marker, t))


def updatewrap(orig, ui, repo, *args, **kwargs):
    ret = orig(ui, repo, *args, **kwargs)
    pctx = repo['.']
    if pctx.phase() == phases.public and repo.vfs.exists('topic'):
        repo.vfs.unlink('topic')
    else:
        # inherit the topic of the parent revision
        t = pctx.extra().get('topic', '')
        if t and pctx.phase() > phases.public:
            with repo.vfs.open('topic', 'w') as f:
                f.write(t)
    return ret

extensions.wrapcommand(commands.table, 'update', updatewrap)