diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py index 3340d46a5c3f1ac61d133369df0ecc725a1a5267_bWVyY3VyaWFsL2J1bmRsZTIucHk=..dbf868623daf6faaf106b19f5f80110aef63be80_bWVyY3VyaWFsL2J1bmRsZTIucHk= 100644 --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -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