changeset 3263:678a9802c56b

topic: add an option to automatically publish topic-less changeset This new option will help playing with merge based workflow.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 01 Nov 2017 16:26:33 +0100
parents f286eefbd20d
children 90515d0bfb08
files CHANGELOG hgext3rd/topic/__init__.py hgext3rd/topic/flow.py tests/test-topic-flow-publish-bare.t
diffstat 4 files changed, 345 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,8 @@
 
   * add an experimental flag to enforce one head per name policy,
     (off by default, see 'hg help -e topic' for details)
+  * add an experimental flag to have changesets without topic published on push,
+    (off by default, see 'hg help -e topic' for details)
 
 6.8.0 -- 2017-10-23
 -------------------
--- a/hgext3rd/topic/__init__.py
+++ b/hgext3rd/topic/__init__.py
@@ -72,6 +72,27 @@
 
     [experimental]
     enforce-single-head = yes
+
+Publishing behavior
+===================
+
+Topic vanish when changeset move to the public phases. Moving to the public
+phase usually happens on push, but it is possible ot update that behavior. The
+server needs to have specific config for this.
+
+    # everything pushed become public (the default)
+    [phase]
+    publish = yes
+
+    # nothing push turned public
+    [phase]
+    publish = no
+
+    # topic branches are not published, changeset without topic are
+    [phase]
+    publish = no
+    [experimental]
+    topic.publish-bare-branch = yes
 """
 
 from __future__ import absolute_import
@@ -168,6 +189,9 @@
     configitem('experimental', 'topic-mode',
                default=None,
     )
+    configitem('experimental', 'topic.publish-bare-branch',
+               default=False,
+    )
     configitem('_internal', 'keep-topic',
                default=False,
     )
@@ -381,8 +405,8 @@
             if desc in ('strip', 'repair') or ctr is not None:
                 return tr
 
+            reporef = weakref.ref(self)
             if repo.ui.configbool('experimental', 'enforce-single-head'):
-                reporef = weakref.ref(self)
                 origvalidator = tr.validator
 
                 def validator(tr2):
@@ -391,6 +415,20 @@
                     origvalidator(tr2)
                 tr.validator = validator
 
+            if (repo.ui.configbool('experimental', 'topic.publish-bare-branch')
+                    and (desc.startswith('push')
+                         or desc.startswith('serve'))
+                    ):
+                origclose = tr.close
+                trref = weakref.ref(tr)
+
+                def close():
+                    repo = reporef()
+                    tr2 = trref()
+                    flow.publishbarebranch(repo, tr2)
+                    origclose()
+                tr.close = close
+
             # real transaction start
             ct = self.currenttopic
             if not ct:
--- a/hgext3rd/topic/flow.py
+++ b/hgext3rd/topic/flow.py
@@ -3,6 +3,7 @@
 from mercurial import (
     error,
     node,
+    phases,
 )
 
 from mercurial.i18n import _
@@ -13,3 +14,14 @@
             hexs = [node.short(n) for n in heads]
             raise error.Abort(_('%d heads on "%s"') % (len(heads), name),
                               hint=(', '.join(hexs)))
+
+def publishbarebranch(repo, tr):
+    """Publish changeset without topic"""
+    if 'node' not in tr.hookargs: # no new node
+        return
+    startnode = node.bin(tr.hookargs['node'])
+    topublish = repo.revs('not public() and (%n:) - hidden() - topic()', startnode)
+    if topublish:
+        cl = repo.changelog
+        nodes = [cl.node(r) for r in topublish]
+        repo._phasecache.advanceboundary(repo, tr, phases.public, nodes)
new file mode 100644
--- /dev/null
+++ b/tests/test-topic-flow-publish-bare.t
@@ -0,0 +1,292 @@
+=====================
+Test workflow options
+=====================
+
+  $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ . "$TESTDIR/testlib/common.sh"
+
+Publishing of bare branch
+=========================
+
+  $ hg init bare-branch-server
+  $ cd bare-branch-server
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish = no
+  > [experimental]
+  > topic.publish-bare-branch = yes
+  > EOF
+  $ mkcommit ROOT
+  $ mkcommit c_dA0
+  $ hg phase --public -r 'all()'
+  $ cd ..
+
+  $ hg clone bare-branch-server bare-client
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+pushing a simple branch publish it
+----------------------------------
+
+  $ cd bare-client
+  $ mkcommit c_dB0
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+pushing two heads at the same time
+----------------------------------
+
+  $ hg update 'desc("c_dA0")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit c_dC0
+  created new head
+  $ hg update 'desc("c_dA0")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit c_dD0
+  created new head
+  $ hg push -f
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files (+2 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  4:9bf953aa81f6 c_dD0 public default
+  |
+  | o  3:9d5b8e1f08a4 c_dC0 public default
+  |/
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+pushing something not on default
+--------------------------------
+
+  $ hg update 'desc("ROOT")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg branch branchA
+  marked working directory as branch branchA
+  (branches are permanent and global, did you want a bookmark?)
+  $ mkcommit c_aE0
+  $ hg push --new-branch
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  5:0db08e758601 c_aE0 public branchA
+  |
+  | o  4:9bf953aa81f6 c_dD0 public default
+  | |
+  | | o  3:9d5b8e1f08a4 c_dC0 public default
+  | |/
+  | | o  2:286d02a6e2a2 c_dB0 public default
+  | |/
+  | o  1:134bc3852ad2 c_dA0 public default
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+pushing topic
+-------------
+
+  $ hg update 'desc("c_dD0")'
+  2 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg topic foo
+  marked working directory as topic: foo
+  $ mkcommit c_dF0
+  active topic 'foo' grew its first changeset
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  6:0867c4471796 c_dF0 draft default foo
+  |
+  o  4:9bf953aa81f6 c_dD0 public default
+  |
+  | o  3:9d5b8e1f08a4 c_dC0 public default
+  |/
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+pushing topic over a bare branch
+--------------------------------
+
+  $ hg update 'desc("c_dC0")'
+  1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ mkcommit c_dG0
+  $ hg topic bar
+  marked working directory as topic: bar
+  $ mkcommit c_dH0
+  active topic 'bar' grew its first changeset
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  8:858be9a8daaf c_dH0 draft default bar
+  |
+  o  7:0e4041d324d0 c_dG0 public default
+  |
+  o  3:9d5b8e1f08a4 c_dC0 public default
+  |
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  | o  6:0867c4471796 c_dF0 draft default foo
+  | |
+  | o  4:9bf953aa81f6 c_dD0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+Pushing topic in between bare branch
+------------------------------------
+
+  $ hg update 'desc("c_dB0")'
+  1 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ mkcommit c_dI0
+  $ hg update 'desc("c_dH0")'
+  switching to topic bar
+  3 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ mkcommit c_dJ0
+  $ hg update 'desc("c_aE0")'
+  1 files updated, 0 files merged, 5 files removed, 0 files unresolved
+  $ mkcommit c_aK0
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 3 changes to 3 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  11:b0a00ebdfd24 c_aK0 public branchA
+  |
+  o  5:0db08e758601 c_aE0 public branchA
+  |
+  | o  10:abb5c84eb9e9 c_dJ0 draft default bar
+  | |
+  | o  8:858be9a8daaf c_dH0 draft default bar
+  | |
+  | o  7:0e4041d324d0 c_dG0 public default
+  | |
+  | o  3:9d5b8e1f08a4 c_dC0 public default
+  | |
+  | | o  9:4b5570d89f0f c_dI0 public default
+  | | |
+  | | o  2:286d02a6e2a2 c_dB0 public default
+  | |/
+  | | o  6:0867c4471796 c_dF0 draft default foo
+  | | |
+  | | o  4:9bf953aa81f6 c_dD0 public default
+  | |/
+  | o  1:134bc3852ad2 c_dA0 public default
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+merging a topic in branch
+-------------------------
+
+  $ hg update default
+  3 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg merge foo
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m 'c_dL0'
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files (-1 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @    12:a6f9f8c6c6cc c_dL0 public default
+  |\
+  | o  9:4b5570d89f0f c_dI0 public default
+  | |
+  o |  6:0867c4471796 c_dF0 public default
+  | |
+  o |  4:9bf953aa81f6 c_dD0 public default
+  | |
+  | | o  10:abb5c84eb9e9 c_dJ0 draft default bar
+  | | |
+  | | o  8:858be9a8daaf c_dH0 draft default bar
+  | | |
+  | | o  7:0e4041d324d0 c_dG0 public default
+  | | |
+  +---o  3:9d5b8e1f08a4 c_dC0 public default
+  | |
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  11:b0a00ebdfd24 c_aK0 public branchA
+  | |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+  
+  $ hg log -R ../bare-branch-server --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  o    12:a6f9f8c6c6cc c_dL0 public default
+  |\
+  | o  9:4b5570d89f0f c_dI0 public default
+  | |
+  o |  6:0867c4471796 c_dF0 public default
+  | |
+  o |  4:9bf953aa81f6 c_dD0 public default
+  | |
+  | | o  10:abb5c84eb9e9 c_dJ0 draft default bar
+  | | |
+  | | o  8:858be9a8daaf c_dH0 draft default bar
+  | | |
+  | | o  7:0e4041d324d0 c_dG0 public default
+  | | |
+  +---o  3:9d5b8e1f08a4 c_dC0 public default
+  | |
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  @  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  11:b0a00ebdfd24 c_aK0 public branchA
+  | |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+