mercurial/scmutil.py
changeset 33331 4bae3c117b57
parent 33330 ba43e5ee9c6d
child 33352 967ac37f3d45
--- a/mercurial/scmutil.py	Mon Jun 26 15:08:37 2017 -0700
+++ b/mercurial/scmutil.py	Mon Jun 26 13:13:51 2017 -0700
@@ -567,6 +567,16 @@
 
     return fullorigpath + ".orig"
 
+class _containsnode(object):
+    """proxy __contains__(node) to container.__contains__ which accepts revs"""
+
+    def __init__(self, repo, revcontainer):
+        self._torev = repo.changelog.rev
+        self._revcontains = revcontainer.__contains__
+
+    def __contains__(self, node):
+        return self._revcontains(self._torev(node))
+
 def cleanupnodes(repo, mapping, operation):
     """do common cleanups when old nodes are replaced by new nodes
 
@@ -583,17 +593,16 @@
         # Move bookmarks
         bmarks = repo._bookmarks
         bmarkchanged = False
+        allnewnodes = [n for ns in mapping.values() for n in ns]
         for oldnode, newnodes in mapping.items():
             oldbmarks = repo.nodebookmarks(oldnode)
             if not oldbmarks:
                 continue
+            from . import bookmarks # avoid import cycle
             bmarkchanged = True
             if len(newnodes) > 1:
-                heads = list(repo.set('heads(%ln)', newnodes))
-                if len(heads) != 1:
-                    raise error.ProgrammingError(
-                        'cannot figure out bookmark movement')
-                newnode = heads[0].node()
+                # usually a split, take the one with biggest rev number
+                newnode = next(repo.set('max(%ln)', newnodes)).node()
             elif len(newnodes) == 0:
                 # move bookmark backwards
                 roots = list(repo.set('max((::%n) - %ln)', oldnode,
@@ -606,8 +615,13 @@
                 newnode = newnodes[0]
             repo.ui.debug('moving bookmarks %r from %s to %s\n' %
                           (oldbmarks, hex(oldnode), hex(newnode)))
+            # Delete divergent bookmarks being parents of related newnodes
+            deleterevs = repo.revs('parents(roots(%ln & (::%n))) - parents(%n)',
+                                   allnewnodes, newnode, oldnode)
+            deletenodes = _containsnode(repo, deleterevs)
             for name in oldbmarks:
                 bmarks[name] = newnode
+                bookmarks.deletedivergent(repo, deletenodes, name)
         if bmarkchanged:
             bmarks.recordchange(tr)