src/topic/__init__.py
author Matt Mackall <mpm@selenic.com>
Wed, 10 Jun 2015 16:32:20 -0500
changeset 1848 9a81657deec2
parent 1847 9fa5b8f4e98e
child 1849 9218f91619f6
permissions -rw-r--r--
summary: add topic summary hook
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     1
# __init__.py - topic extension
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     2
#
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     3
# This software may be used and distributed according to the terms of the
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     4
# GNU General Public License version 2 or any later version.
1846
0b5b757ca812 docs: fix format of extension docstring
Matt Mackall <mpm@selenic.com>
parents: 1845
diff changeset
     5
"""support for topic branches
0b5b757ca812 docs: fix format of extension docstring
Matt Mackall <mpm@selenic.com>
parents: 1845
diff changeset
     6
0b5b757ca812 docs: fix format of extension docstring
Matt Mackall <mpm@selenic.com>
parents: 1845
diff changeset
     7
Topic branches are lightweight branches which
0b5b757ca812 docs: fix format of extension docstring
Matt Mackall <mpm@selenic.com>
parents: 1845
diff changeset
     8
disappear when changes are finalized.
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     9
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    10
This is sort of similar to a bookmark, but it applies to a whole
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    11
series instead of a single revision.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    12
"""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
import functools
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
1848
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
    15
from mercurial.i18n import _
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
from mercurial import cmdutil
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
from mercurial import commands
1844
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    18
from mercurial import context
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
from mercurial import extensions
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
from mercurial import namespaces
1842
94bbc18daa99 topic: disallow use of topics without obsolete enabled
Augie Fackler <augie@google.com>
parents: 1841
diff changeset
    21
from mercurial import obsolete
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    22
from mercurial import phases
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
from mercurial import util
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    24
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    25
from . import constants
1843
0ba067a97d06 revset: add a topic() revset for querying topics
Augie Fackler <augie@google.com>
parents: 1842
diff changeset
    26
from . import revset as topicrevset
0ba067a97d06 revset: add a topic() revset for querying topics
Augie Fackler <augie@google.com>
parents: 1842
diff changeset
    27
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
cmdtable = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    29
command = cmdutil.command(cmdtable)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    30
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    31
def _namemap(repo, name):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
    return [ctx.node() for ctx in
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
            repo.set('not public() and extra(topic, %s)', name)]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
def _nodemap(repo, node):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
    ctx = repo[node]
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    37
    t = ctx.extra().get(constants.extrakey, '')
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
    if t and ctx.phase() > phases.public:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
        return [t]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
    return []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
def reposetup(ui, repo):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
    orig = repo.__class__
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
    class topicrepo(repo.__class__):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
        def commitctx(self, ctx, error=None):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
            current = self.currenttopic
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
            if current:
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    48
                ctx.extra()[constants.extrakey] = current
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
            return orig.commitctx(self, ctx, error=error)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
        @property
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
        def topics(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
            topics = set(['', self.currenttopic])
1841
72a58a5bfb62 topic: use repo.set() where we need a changectx anyway
Augie Fackler <augie@google.com>
parents: 1839
diff changeset
    54
            for c in self.set('not public()'):
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    55
                topics.add(c.extra().get(constants.extrakey, ''))
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
            topics.remove('')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    57
            return topics
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
        @property
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
        def currenttopic(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
            return self.vfs.tryread('topic')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
    if util.safehasattr(repo, 'names'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
        repo.names.addnamespace(namespaces.namespace(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
            'topics', 'topic', namemap=_namemap, nodemap=_nodemap))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
    repo.__class__ = topicrepo
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
1847
9fa5b8f4e98e topics: add command summary
Matt Mackall <mpm@selenic.com>
parents: 1846
diff changeset
    68
@command('topics [TOPIC]', [
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
    ('', 'clear', False, 'clear active topic if any'),
1844
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    70
    ('', 'change', '', 'revset of existing revisions to change topic'),
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    71
])
1844
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    72
def topics(ui, repo, topic=None, clear=False, change=None):
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    73
    """View current topic, set current topic, or see all topics."""
1842
94bbc18daa99 topic: disallow use of topics without obsolete enabled
Augie Fackler <augie@google.com>
parents: 1841
diff changeset
    74
    if not obsolete.isenabled(repo, obsolete.createmarkersopt):
94bbc18daa99 topic: disallow use of topics without obsolete enabled
Augie Fackler <augie@google.com>
parents: 1841
diff changeset
    75
        raise util.Abort('current reality means you should only '
94bbc18daa99 topic: disallow use of topics without obsolete enabled
Augie Fackler <augie@google.com>
parents: 1841
diff changeset
    76
                         'use topic with obsolete enabled')
1844
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    77
    if change:
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    78
        if topic is None and not clear:
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    79
            raise util.Abort('changing topic requires a topic name or --clear')
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    80
        if any(not c.mutable() for c in repo.set('%r and public()', change)):
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    81
            raise util.Abort("can't change topic of a public change")
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    82
        rewrote = 0
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    83
        needevolve = False
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    84
        for c in repo.set('%r', change):
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    85
            def filectxfn(repo, ctx, path):
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    86
                try:
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    87
                    return c[path]
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    88
                except error.ManifestLookupError:
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    89
                    return None
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    90
            fixedextra = dict(c.extra())
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    91
            newtopic = None if clear else topic
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    92
            if fixedextra.get(constants.extrakey, None) == topic:
1844
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    93
                continue
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    94
            if clear and constants.extrakey in fixedextra:
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    95
                del fixedextra[constants.extrakey]
1844
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    96
            else:
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
    97
                fixedextra[constants.extrakey] = topic
1844
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    98
            c.parents()
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
    99
            mc = context.memctx(
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   100
                repo, (c.p1().node(), c.p2().node()), c.description(),
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   101
                c.files(), filectxfn,
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   102
                user=c.user(), date=c.date(), extra=fixedextra)
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   103
            newnode = repo.commitctx(mc)
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   104
            needevolve = needevolve or (len(c.children()) > 0)
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   105
            obsolete.createmarkers(repo, [(c, (repo[newnode],))])
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   106
            rewrote += 1
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   107
        ui.status('changed topic on %d changes\n' % rewrote)
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   108
        if needevolve:
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   109
            evolvetarget = 'topic(%s)' % topic if topic else 'not topic()'
862cabc132fd topic: add ability to change topic of non-public changes
Augie Fackler <augie@google.com>
parents: 1843
diff changeset
   110
            ui.status('please run hg evolve --rev "%s" now\n' % evolvetarget)
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   111
    if clear:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
        if repo.vfs.exists('topic'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
            repo.vfs.unlink('topic')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
        return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
    if topic is not None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
        with repo.vfs.open('topic', 'w') as f:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
            f.write(topic)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
        return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
    current = repo.currenttopic
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
    for t in sorted(repo.topics):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
        marker = '*' if t == current else ' '
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   122
        ui.write(' %s %s\n' % (marker, t))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
1848
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
   124
def summaryhook(ui, repo):
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
   125
    t = repo.currenttopic
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
   126
    if not t:
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
   127
        return
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
   128
    # i18n: column positioning for "hg summary"
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
   129
    ui.write(_("topic:  %s\n") % t)
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   130
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   131
def updatewrap(orig, ui, repo, *args, **kwargs):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   132
    ret = orig(ui, repo, *args, **kwargs)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   133
    pctx = repo['.']
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   134
    if pctx.phase() == phases.public and repo.vfs.exists('topic'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
        repo.vfs.unlink('topic')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   136
    else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   137
        # inherit the topic of the parent revision
1845
24d8053020a2 constants: extract key for extra into a constant
Augie Fackler <augie@google.com>
parents: 1844
diff changeset
   138
        t = pctx.extra().get(constants.extrakey, '')
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
        if t and pctx.phase() > phases.public:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   140
            with repo.vfs.open('topic', 'w') as f:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
                f.write(t)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
    return ret
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   143
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   144
extensions.wrapcommand(commands.table, 'update', updatewrap)
1843
0ba067a97d06 revset: add a topic() revset for querying topics
Augie Fackler <augie@google.com>
parents: 1842
diff changeset
   145
topicrevset.modsetup()
1848
9a81657deec2 summary: add topic summary hook
Matt Mackall <mpm@selenic.com>
parents: 1847
diff changeset
   146
cmdutil.summaryhooks.add('topic', summaryhook)