mercurial/bundle2.py
changeset 35267 dbf868623daf
parent 35141 699b2a759319
child 35268 ad5f2b923b0d
--- a/mercurial/bundle2.py	Sun Oct 15 14:59:55 2017 +0200
+++ b/mercurial/bundle2.py	Sun Oct 15 15:01:03 2017 +0200
@@ -156,6 +156,7 @@
 
 from .i18n import _
 from . import (
+    bookmarks,
     changegroup,
     error,
     node as nodemod,
@@ -1787,6 +1788,34 @@
     replyto = int(inpart.params['in-reply-to'])
     op.records.add('changegroup', {'return': ret}, replyto)
 
+@parthandler('check:bookmarks')
+def handlecheckbookmarks(op, inpart):
+    """check location of bookmarks
+
+    This part is to be used to detect push race regarding bookmark, it
+    contains binary encoded (bookmark, node) tuple. If the local state does
+    not marks the one in the part, a PushRaced exception is raised
+    """
+    bookdata = bookmarks.binarydecode(inpart)
+
+    msgstandard = ('repository changed while pushing - please try again '
+                   '(bookmark "%s" move from %s to %s)')
+    msgmissing = ('repository changed while pushing - please try again '
+                  '(bookmark "%s" is missing, expected %s)')
+    msgexist = ('repository changed while pushing - please try again '
+                '(bookmark "%s" set on %s, expected missing)')
+    for book, node in bookdata:
+        currentnode = op.repo._bookmarks.get(book)
+        if currentnode != node:
+            if node is None:
+                finalmsg = msgexist % (book, nodemod.short(currentnode))
+            elif currentnode is None:
+                finalmsg = msgmissing % (book, nodemod.short(node))
+            else:
+                finalmsg = msgstandard % (book, nodemod.short(node),
+                                          nodemod.short(currentnode))
+            raise error.PushRaced(finalmsg)
+
 @parthandler('check:heads')
 def handlecheckheads(op, inpart):
     """check that head of the repo did not change