src/topic/__init__.py
changeset 1844 862cabc132fd
parent 1843 0ba067a97d06
child 1845 24d8053020a2
--- a/src/topic/__init__.py	Wed Jun 10 15:26:50 2015 -0400
+++ b/src/topic/__init__.py	Wed Jun 10 15:03:39 2015 -0400
@@ -12,6 +12,7 @@
 
 from mercurial import cmdutil
 from mercurial import commands
+from mercurial import context
 from mercurial import extensions
 from mercurial import namespaces
 from mercurial import obsolete
@@ -62,12 +63,47 @@
 
 @command('topics', [
     ('', 'clear', False, 'clear active topic if any'),
+    ('', 'change', '', 'revset of existing revisions to change topic'),
 ])
-def topics(ui, repo, topic=None, clear=False):
+def topics(ui, repo, topic=None, clear=False, change=None):
     """View current topic, set current topic, or see all topics."""
     if not obsolete.isenabled(repo, obsolete.createmarkersopt):
         raise util.Abort('current reality means you should only '
                          'use topic with obsolete enabled')
+    if 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('topic', None) == topic:
+                continue
+            if clear and 'topic' in fixedextra:
+                del fixedextra['topic']
+            else:
+                fixedextra['topic'] = 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')