Mercurial > evolve
view src/topic/__init__.py @ 1852:3084687f7994
commit: add a topic field to the in-editor commit text
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 10 Jun 2015 17:52:07 -0500 |
parents | 67d53e8e0c1a |
children | 8db7828751b7 |
line wrap: on
line source
# __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. """support for topic branches Topic branches are lightweight branches which disappear 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.i18n import _ from mercurial import cmdutil from mercurial import commands from mercurial import context from mercurial import extensions from mercurial import namespaces from mercurial import obsolete from mercurial import phases from mercurial import util from . import constants from . import revset as topicrevset 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(constants.extrakey, '') 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()[constants.extrakey] = current return orig.commitctx(self, ctx, error=error) @property def topics(self): topics = set(['', self.currenttopic]) for c in self.set('not public()'): topics.add(c.extra().get(constants.extrakey, '')) 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 [TOPIC]', [ ('', 'clear', False, 'clear active topic if any'), ('', 'change', '', 'revset of existing revisions to change topic'), ]) def topics(ui, repo, topic=None, clear=False, change=None): """View current topic, set current topic, or see all topics.""" if change: if not obsolete.isenabled(repo, obsolete.createmarkersopt): raise util.Abort(_('must have obsolete enabled to use --change')) if topic is None and not clear: raise util.Abort('changing topic requires a topic name or --clear') if any(not c.mutable() for c in repo.set('%r and public()', change)): raise util.Abort("can't change topic of a public change") rewrote = 0 needevolve = False for c in repo.set('%r', change): def filectxfn(repo, ctx, path): try: return c[path] except error.ManifestLookupError: return None fixedextra = dict(c.extra()) newtopic = None if clear else topic if fixedextra.get(constants.extrakey, None) == topic: continue if clear and constants.extrakey in fixedextra: del fixedextra[constants.extrakey] else: fixedextra[constants.extrakey] = topic c.parents() mc = context.memctx( repo, (c.p1().node(), c.p2().node()), c.description(), c.files(), filectxfn, user=c.user(), date=c.date(), extra=fixedextra) newnode = repo.commitctx(mc) needevolve = needevolve or (len(c.children()) > 0) obsolete.createmarkers(repo, [(c, (repo[newnode],))]) rewrote += 1 ui.status('changed topic on %d changes\n' % rewrote) if needevolve: evolvetarget = 'topic(%s)' % topic if topic else 'not topic()' ui.status('please run hg evolve --rev "%s" now\n' % evolvetarget) 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 summaryhook(ui, repo): t = repo.currenttopic if not t: return # i18n: column positioning for "hg summary" ui.write(_("topic: %s\n") % t) def commitwrap(orig, ui, repo, *args, **opts): if opts.get('topic'): t = opts['topic'] with repo.vfs.open('topic', 'w') as f: f.write(t) return orig(ui, repo, *args, **opts) def committextwrap(orig, repo, ctx, subs, extramsg): ret = orig(repo, ctx, subs, extramsg) t = repo.currenttopic if t: ret = ret.replace("\nHG: branch", "\nHG: topic '%s'\nHG: branch" % t) return ret def updatewrap(orig, ui, repo, *args, **kwargs): ret = orig(ui, repo, *args, **kwargs) pctx = repo['.'] ot = repo.currenttopic 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(constants.extrakey, '') if t and pctx.phase() > phases.public: with repo.vfs.open('topic', 'w') as f: f.write(t) if t != ot: ui.status(_("switching to topic %s\n") % t) return ret entry = extensions.wrapcommand(commands.table, 'commit', commitwrap) entry[1].append(('t', 'topic', '', _("use specified topic"), _('TOPIC'))) extensions.wrapcommand(commands.table, 'update', updatewrap) extensions.wrapfunction(cmdutil, 'buildcommittext', committextwrap) topicrevset.modsetup() cmdutil.summaryhooks.add('topic', summaryhook)