[PATCH 1 of 5] bundle2: introduce a PushkeyFail error to abort unbundle on pushkey error

Pierre-Yves David pierre-yves.david at ens-lyon.org
Mon Jun 8 12:29:15 CDT 2015

# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1432795734 25200
#      Wed May 27 23:48:54 2015 -0700
# Node ID 3dde3db78235e4aaa2e184e2dac73e9a8d27d74c
# Parent  40c4968954f175698a21ddb11aaa3db4c72c3887
bundle2: introduce a PushkeyFail error to abort unbundle on pushkey error

The pushkey code is generic and the server side have few context on what the
client is trying to achieve. Generating interesting error message server side
would be challenging. Instead we introduce a dedicated exception that carry more
data. In particular, it carry the id of the part who failed, that will allow
clients to display custom error messages depending of the part intend.

The processing and transfer-over-the-wire of this exception is to be implemented
in coming changesets.

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -1328,12 +1328,15 @@ def handlepushkey(op, inpart):
     if op.reply is not None:
         rpart = op.reply.newpart('reply:pushkey')
         rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
         rpart.addparam('return', '%i' % ret, mandatory=False)
     if inpart.mandatory and not ret:
-        raise util.Abort(_('failed to update value for "%s/%s"')
-                         % (namespace, key))
+        kwargs = {}
+        for key in ('namespace', 'key', 'new', 'old', 'ret'):
+            if key in inpart.params:
+                kwargs[key] = inpart.params[key]
+        raise error.PushkeyFailed(partid=str(inpart.id), **kwargs)
 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
 def handlepushkeyreply(op, inpart):
     """retrieve the result of a pushkey request"""
     ret = int(inpart.params['return'])
diff --git a/mercurial/error.py b/mercurial/error.py
--- a/mercurial/error.py
+++ b/mercurial/error.py
@@ -149,10 +149,25 @@ class UnsupportedPartError(BundleValueEr
 class ReadOnlyPartError(RuntimeError):
     """error raised when code tries to alter a part being generated"""
+class PushkeyFailed(Abort):
+    """error raised when a pushkey part failed to update a value"""
+    def __init__(self, partid, namespace=None, key=None, new=None, old=None,
+                 ret=None):
+        self.partid = partid
+        self.namespace = namespace
+        self.key = key
+        self.new = new
+        self.old = old
+        self.ret = ret
+        # no i18n expected to be processed into a better message
+        Abort.__init__(self, 'failed to update value for "%s/%s"'
+                       % (namespace, key))
 class CensoredNodeError(RevlogError):
     """error raised when content verification fails on a censored node
     Also contains the tombstone data substituted for the uncensored data.

More information about the Mercurial-devel mailing list