changeset 34820:a95067b1dca6

phase: introduce a new 'check:phases' part This part checks if revisions are still in the same phase as when the bundle was generated. This is similar to what 'check:heads' or 'check:updated-heads' bundle2 part achieves for changesets. We needs seems before we can move away from pushkey usage from phase since pushkey has it own built-in push-race detection.
author Boris Feld <boris.feld@octobus.net>
date Wed, 11 Oct 2017 07:13:02 +0200
parents eb6375651974
children aa5e7b4a3a01
files mercurial/bundle2.py
diffstat 1 files changed, 22 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/bundle2.py	Wed Oct 11 18:39:04 2017 +0200
+++ b/mercurial/bundle2.py	Wed Oct 11 07:13:02 2017 +0200
@@ -157,6 +157,7 @@
 from . import (
     changegroup,
     error,
+    node as nodemod,
     obsolete,
     phases,
     pushkey,
@@ -1749,6 +1750,27 @@
             raise error.PushRaced('repository changed while pushing - '
                                   'please try again')
 
+@parthandler('check:phases')
+def handlecheckphases(op, inpart):
+    """check that phase boundaries of the repository did not change
+
+    This is used to detect a push race.
+    """
+    phasetonodes = phases.binarydecode(inpart)
+    unfi = op.repo.unfiltered()
+    cl = unfi.changelog
+    phasecache = unfi._phasecache
+    msg = ('repository changed while pushing - please try again '
+           '(%s is %s expected %s)')
+    for expectedphase, nodes in enumerate(phasetonodes):
+        for n in nodes:
+            actualphase = phasecache.phase(unfi, cl.rev(n))
+            if actualphase != expectedphase:
+                finalmsg = msg % (nodemod.short(n),
+                                  phases.phasenames[actualphase],
+                                  phases.phasenames[expectedphase])
+                raise error.PushRaced(finalmsg)
+
 @parthandler('output')
 def handleoutput(op, inpart):
     """forward output captured on the server to the client"""