changeset 23590:4440c7cc3728

bundle2.bundlepart: make mandatory part flag explicit in API This makes all bundle2 parts mandatory unless they are expressly made advisory via the keyword parameter or the bundlepart.mandatory property.
author Eric Sumner <ericsumner@fb.com>
date Wed, 17 Dec 2014 21:14:19 -0800
parents 200215cdf7aa
children 414374cfb531
files mercurial/bundle2.py tests/test-bundle2-format.t
diffstat 2 files changed, 25 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/bundle2.py	Wed Dec 17 15:09:43 2014 +0900
+++ b/mercurial/bundle2.py	Wed Dec 17 21:14:19 2014 -0800
@@ -350,7 +350,8 @@
             if output is not None:
                 output = op.ui.popbuffer()
         if output:
-            outpart = op.reply.newpart('b2x:output', data=output)
+            outpart = op.reply.newpart('b2x:output', data=output,
+                                       mandatory=False)
             outpart.addparam('in-reply-to', str(part.id), mandatory=False)
     finally:
         # consume the part content to not corrupt the stream.
@@ -588,7 +589,7 @@
     """
 
     def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
-                 data=''):
+                 data='', mandatory=True):
         self.id = None
         self.type = parttype
         self._data = data
@@ -605,6 +606,7 @@
         # - False: currently generated,
         # - True: generation done.
         self._generated = None
+        self.mandatory = mandatory
 
     # methods used to defines the part content
     def __setdata(self, data):
@@ -642,9 +644,13 @@
             raise RuntimeError('part can only be consumed once')
         self._generated = False
         #### header
+        if self.mandatory:
+            parttype = self.type.upper()
+        else:
+            parttype = self.type.lower()
         ## parttype
-        header = [_pack(_fparttypesize, len(self.type)),
-                  self.type, _pack(_fpartid, self.id),
+        header = [_pack(_fparttypesize, len(parttype)),
+                  parttype, _pack(_fpartid, self.id),
                  ]
         ## parameters
         # count
@@ -681,7 +687,8 @@
             # backup exception data for later
             exc_info = sys.exc_info()
             msg = 'unexpected error: %s' % exc
-            interpart = bundlepart('b2x:error:abort', [('message', msg)])
+            interpart = bundlepart('b2x:error:abort', [('message', msg)],
+                                   mandatory=False)
             interpart.id = 0
             yield _pack(_fpayloadsize, -1)
             for chunk in interpart.getchunks():
@@ -930,7 +937,7 @@
     if op.reply is not None:
         # This is definitely not the final form of this
         # return. But one need to start somewhere.
-        part = op.reply.newpart('b2x:reply:changegroup')
+        part = op.reply.newpart('b2x:reply:changegroup', mandatory=False)
         part.addparam('in-reply-to', str(inpart.id), mandatory=False)
         part.addparam('return', '%i' % ret, mandatory=False)
     assert not inpart.read()
--- a/tests/test-bundle2-format.t	Wed Dec 17 15:09:43 2014 +0900
+++ b/tests/test-bundle2-format.t	Wed Dec 17 21:14:19 2014 -0800
@@ -55,7 +55,8 @@
   >     op.ui.write('received ping request (id %i)\n' % part.id)
   >     if op.reply is not None and 'ping-pong' in op.reply.capabilities:
   >         op.ui.write_err('replying to ping request (id %i)\n' % part.id)
-  >         op.reply.newpart('test:pong', [('in-reply-to', str(part.id))])
+  >         op.reply.newpart('test:pong', [('in-reply-to', str(part.id))],
+  >                          mandatory=False)
   > 
   > @bundle2.parthandler('test:debugreply')
   > def debugreply(op, part):
@@ -108,32 +109,34 @@
   >             headcommon  = [c.node() for c in repo.set('parents(%ld) - %ld', revs, revs)]
   >             outgoing = discovery.outgoing(repo.changelog, headcommon, headmissing)
   >             cg = changegroup.getlocalchangegroup(repo, 'test:bundle2', outgoing, None)
-  >             bundler.newpart('b2x:changegroup', data=cg.getchunks())
+  >             bundler.newpart('b2x:changegroup', data=cg.getchunks(),
+  >                             mandatory=False)
   > 
   >     if opts['parts']:
-  >        bundler.newpart('test:empty')
+  >        bundler.newpart('test:empty', mandatory=False)
   >        # add a second one to make sure we handle multiple parts
-  >        bundler.newpart('test:empty')
-  >        bundler.newpart('test:song', data=ELEPHANTSSONG)
-  >        bundler.newpart('test:debugreply')
+  >        bundler.newpart('test:empty', mandatory=False)
+  >        bundler.newpart('test:song', data=ELEPHANTSSONG, mandatory=False)
+  >        bundler.newpart('test:debugreply', mandatory=False)
   >        mathpart = bundler.newpart('test:math')
   >        mathpart.addparam('pi', '3.14')
   >        mathpart.addparam('e', '2.72')
   >        mathpart.addparam('cooking', 'raw', mandatory=False)
   >        mathpart.data = '42'
+  >        mathpart.mandatory = False
   >        # advisory known part with unknown mandatory param
-  >        bundler.newpart('test:song', [('randomparam','')])
+  >        bundler.newpart('test:song', [('randomparam','')], mandatory=False)
   >     if opts['unknown']:
   >        bundler.newpart('test:UNKNOWN', data='some random content')
   >     if opts['unknownparams']:
   >        bundler.newpart('test:SONG', [('randomparams', '')])
   >     if opts['parts']:
-  >        bundler.newpart('test:ping')
+  >        bundler.newpart('test:ping', mandatory=False)
   >     if opts['genraise']:
   >        def genraise():
   >            yield 'first line\n'
   >            raise RuntimeError('Someone set up us the bomb!')
-  >        bundler.newpart('b2x:output', data=genraise())
+  >        bundler.newpart('b2x:output', data=genraise(), mandatory=False)
   > 
   >     if path is None:
   >        file = sys.stdout