topic: add ability to change topic of non-public changes
authorAugie Fackler <augie@google.com>
Wed, 10 Jun 2015 15:03:39 -0400
changeset 1844 862cabc132fd
parent 1843 0ba067a97d06
child 1845 24d8053020a2
topic: add ability to change topic of non-public changes This is a little crude, but it gets the job done. You probably don't want to use this without evolution for now.
src/topic/__init__.py
tests/test-topic.t
--- 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')
--- a/tests/test-topic.t	Wed Jun 10 15:26:50 2015 -0400
+++ b/tests/test-topic.t	Wed Jun 10 15:03:39 2015 -0400
@@ -14,7 +14,8 @@
   
   options:
   
-    --clear clear active topic if any
+    --clear        clear active topic if any
+    --change VALUE revset of existing revisions to change topic
   
   (some details hidden, use --verbose to show complete help)
   $ hg topics
@@ -438,3 +439,77 @@
   |
   $ hg topics
      fran
+Changing topic fails if we don't give a topic
+  $ hg topic --change 9
+  abort: changing topic requires a topic name or --clear
+  [255]
+
+Can't change topic of a public change
+  $ hg topic --change 1:: --clear
+  abort: can't change topic of a public change
+  [255]
+
+Can clear topics
+  $ hg topic --change 9 --clear
+  changed topic on 1 changes
+  please run hg evolve --rev "not topic()" now
+  $ hg log -Gr 'draft() and not obsolete()'
+  o  changeset:   11:783930e1d79e
+  |  tag:         tip
+  |  parent:      3:a53952faf762
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     start on fran
+  |
+  | @  changeset:   10:4073470c35e1
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     fran?
+  | |
+
+Normally you'd do this with evolve, but we'll use rebase to avoid
+bonus deps in the testsuite.
+
+  $ hg rebase -d tip -s .
+  rebasing 10:4073470c35e1 "fran?"
+
+Can add a topic to an existing change
+  $ hg topic --change 11 wat
+  changed topic on 1 changes
+  please run hg evolve --rev "topic(wat)" now
+  $ hg log -Gr 'draft() and not obsolete()'
+  o  changeset:   13:d91cd8fd490e
+  |  tag:         tip
+  |  topic:       wat
+  |  parent:      3:a53952faf762
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     start on fran
+  |
+  | @  changeset:   12:d9e32f4c4806
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     fran?
+  | |
+
+Normally you'd do this with evolve, but we'll use rebase to avoid
+bonus deps in the testsuite.
+
+  $ hg rebase -d tip -s .
+  rebasing 12:d9e32f4c4806 "fran?"
+
+  $ hg log -Gr 'draft()'
+  @  changeset:   14:cf24ad8bbef5
+  |  tag:         tip
+  |  topic:       wat
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     fran?
+  |
+  o  changeset:   13:d91cd8fd490e
+  |  topic:       wat
+  |  parent:      3:a53952faf762
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     start on fran
+  |