topic: fix new head detection when using --publish on a topic
I suspected a bug lurking around there and I found one.
--- a/hgext3rd/topic/discovery.py Tue Nov 07 14:21:19 2017 +0100
+++ b/hgext3rd/topic/discovery.py Tue Nov 14 21:05:59 2017 +0100
@@ -1,5 +1,6 @@
from __future__ import absolute_import
+import collections
import weakref
from mercurial.i18n import _
@@ -31,17 +32,50 @@
publishing = ('phases' not in remote.listkeys('namespaces')
or bool(remote.listkeys('phases').get('publishing', False)))
- if publishing or not remote.capable('topics'):
+ if ((publishing or not remote.capable('topics'))
+ and (pushoparg and not pushop.publish)):
return orig(*args)
+ publishedset = ()
+ remotebranchmap = None
+ origremotebranchmap = remote.branchmap
+ if pushoparg: # < hg-4.4 do not have a --publish flag anyway
+ publishednode = [c.node() for c in pushop.outdatedphases]
+ publishedset = repo.revs('ancestors(%ln + %ln)',
+ publishednode,
+ pushop.remotephases.publicheads)
+
+ rev = repo.unfiltered().changelog.nodemap.get
+
+ def remotebranchmap():
+ # drop topic information from changeset about to be published
+ result = collections.defaultdict(list)
+ for branch, heads in origremotebranchmap().iteritems():
+ if ':' not in branch:
+ result[branch].extend(heads)
+ else:
+ namedbranch = branch.split(':', 1)[0]
+ for h in heads:
+ r = rev(h)
+ if r is not None and r in publishedset:
+ result[namedbranch].append(h)
+ else:
+ result[branch].append(h)
+ for heads in result.itervalues():
+ heads.sort()
+ return result
+
class repocls(repo.__class__):
# awful hack to see branch as "branch:topic"
def __getitem__(self, key):
ctx = super(repocls, self).__getitem__(key)
oldbranch = ctx.branch
+ rev = ctx.rev()
def branch():
branch = oldbranch()
+ if rev in publishedset:
+ return branch
topic = ctx.topic()
if topic:
branch = "%s:%s" % (branch, topic)
@@ -56,6 +90,8 @@
def branchinfo(rev):
branch, close = changelog.branchinfo(rev)
+ if rev in publishedset:
+ return branch, close
topic = repo[rev].topic()
if topic:
branch = "%s:%s" % (branch, topic)
@@ -67,6 +103,7 @@
oldrepocls = repo.__class__
try:
repo.__class__ = repocls
+ remote.branchmap = remotebranchmap
unxx = repo.filtered('unfiltered-topic')
repo.unfiltered = lambda: unxx
if pushoparg:
@@ -83,6 +120,7 @@
if 'unfiltered' in vars(repo):
del repo.unfiltered
repo.__class__ = oldrepocls
+ remote.branchmap = origremotebranchmap
def wireprotobranchmap(orig, repo, proto):
oldrepo = repo.__class__
--- a/tests/test-topic-flow-publish-flag.t Tue Nov 07 14:21:19 2017 +0100
+++ b/tests/test-topic-flow-publish-flag.t Tue Nov 14 21:05:59 2017 +0100
@@ -280,3 +280,147 @@
|
o 0:ea207398892e ROOT public default
+
+Testing --publish interaction with multiple head detection
+============================================================
+
+pushing a topic changeset, publishing it
+----------------------------------------
+
+ $ hg topic topic_A
+ marked working directory as topic: topic_A
+ $ mkcommit c_dK0
+ active topic 'topic_A' grew its first changeset
+ $ hg push -r 'desc("c_dK0")' --publish
+ 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
+ active topic 'topic_A' is now empty
+ $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+ @ 11:d06fc4f891e8 c_dK0 public default
+ |
+ o 10:ac4cf59f2aac c_dJ0 public default
+ |
+ o 9:fbf2be276221 c_dI0 public default
+ |
+ o 5:5576ae39eaee c_dE0 public default
+ |
+ | o 8:8e85646c135f c_oH0 draft other
+ | |
+ | o 7:d293f74a1233 c_oG0 public other
+ | |
+ | o 6:45b23c834b6a c_oF0 public other
+ |/
+ o 4:c63e7dd93a91 c_dD0 public default
+ |
+ o 3:7d56a56d2547 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 a new branch, alongside an existing topic
+-------------------------------------------------
+
+ $ hg topic topic_A
+ $ mkcommit c_dL0
+ active topic 'topic_A' grew its first changeset
+ $ hg push -r 'desc("c_dL0")'
+ 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 update 'desc("c_dK")'
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ mkcommit c_dM0
+ $ hg push -r 'desc("c_dM0")' --publish
+ 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}'
+ @ 13:0d144c8b6c8f c_dM0 public default
+ |
+ | o 12:3c73f6cabf07 c_dL0 draft default topic_A
+ |/
+ o 11:d06fc4f891e8 c_dK0 public default
+ |
+ o 10:ac4cf59f2aac c_dJ0 public default
+ |
+ o 9:fbf2be276221 c_dI0 public default
+ |
+ o 5:5576ae39eaee c_dE0 public default
+ |
+ | o 8:8e85646c135f c_oH0 draft other
+ | |
+ | o 7:d293f74a1233 c_oG0 public other
+ | |
+ | o 6:45b23c834b6a c_oF0 public other
+ |/
+ o 4:c63e7dd93a91 c_dD0 public default
+ |
+ o 3:7d56a56d2547 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 a topic (publishing) alongside and existing branch head
+---------------------------------------------------------------
+
+ $ hg update 'desc("c_dK")'
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg topic topic_B
+ marked working directory as topic: topic_B
+ $ mkcommit c_dN0
+ active topic 'topic_B' grew its first changeset
+ $ hg push -r 'desc("c_dN0")' --publish
+ pushing to $TESTTMP/bare-branch-server
+ searching for changes
+ abort: push creates new remote head 4dcd0be9db96!
+ (merge or see 'hg help push' for details about pushing new heads)
+ [255]
+ $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+ @ 14:4dcd0be9db96 c_dN0 draft default topic_B
+ |
+ | o 13:0d144c8b6c8f c_dM0 public default
+ |/
+ | o 12:3c73f6cabf07 c_dL0 draft default topic_A
+ |/
+ o 11:d06fc4f891e8 c_dK0 public default
+ |
+ o 10:ac4cf59f2aac c_dJ0 public default
+ |
+ o 9:fbf2be276221 c_dI0 public default
+ |
+ o 5:5576ae39eaee c_dE0 public default
+ |
+ | o 8:8e85646c135f c_oH0 draft other
+ | |
+ | o 7:d293f74a1233 c_oG0 public other
+ | |
+ | o 6:45b23c834b6a c_oF0 public other
+ |/
+ o 4:c63e7dd93a91 c_dD0 public default
+ |
+ o 3:7d56a56d2547 c_dC0 public default
+ |
+ o 2:286d02a6e2a2 c_dB0 public default
+ |
+ o 1:134bc3852ad2 c_dA0 public default
+ |
+ o 0:ea207398892e ROOT public default
+