def _payloadchunks(self, chunknum=0): '''seek to specified chunk and start yielding data''' if len(self._chunkindex) == 0: assert chunknum == 0, 'Must start with chunk 0' self._chunkindex.append((0, super(unbundlepart, self).tell())) else: assert chunknum < len(self._chunkindex), \ 'Unknown chunk %d' % chunknum super(unbundlepart, self).seek(self._chunkindex[chunknum][1]) pos = self._chunkindex[chunknum][0] payloadsize = self._unpack(_fpayloadsize)[0] self.ui.debug('payload chunk size: %i\n' % payloadsize) while payloadsize: if payloadsize == flaginterrupt: # interruption detection, the handler will now read a # single part and process it. interrupthandler(self.ui, self._fp)() elif payloadsize < 0: msg = 'negative payload chunk size: %i' % payloadsize raise error.BundleValueError(msg) else: result = self._readexact(payloadsize) chunknum += 1 pos += payloadsize if chunknum == len(self._chunkindex): self._chunkindex.append((pos, super(unbundlepart, self).tell())) yield result payloadsize = self._unpack(_fpayloadsize)[0] self.ui.debug('payload chunk size: %i\n' % payloadsize)
def handlereplycaps(op, inpart): """Used to transmit unknown content error over the wire""" kwargs = {} parttype = inpart.params.get('parttype') if parttype is not None: kwargs['parttype'] = parttype params = inpart.params.get('params') if params is not None: kwargs['params'] = params.split('\0') raise error.BundleValueError(**kwargs)
def _readpartheader(self): """reads a part header size and return the bytes blob returns None if empty""" headersize = self._unpack(_fpartheadersize)[0] if headersize < 0: raise error.BundleValueError('negative part header size: %i' % headersize) self.ui.debug('part header size: %i\n' % headersize) if headersize: return self._readexact(headersize) return None
def payloadchunks(): payloadsize = self._unpack(_fpayloadsize)[0] self.ui.debug('payload chunk size: %i\n' % payloadsize) while payloadsize: if payloadsize == flaginterrupt: # interruption detection, the handler will now read a # single part and process it. interrupthandler(self.ui, self._fp)() elif payloadsize < 0: msg = 'negative payload chunk size: %i' % payloadsize raise error.BundleValueError(msg) else: yield self._readexact(payloadsize) payloadsize = self._unpack(_fpayloadsize)[0] self.ui.debug('payload chunk size: %i\n' % payloadsize)
def params(self): """dictionary of stream level parameters""" self.ui.debug('reading bundle2 stream parameters\n') params = {} paramssize = self._unpack(_fstreamparamsize)[0] if paramssize < 0: raise error.BundleValueError('negative bundle param size: %i' % paramssize) if paramssize: for p in self._readexact(paramssize).split(' '): p = p.split('=', 1) p = [urllib.unquote(i) for i in p] if len(p) < 2: p.append(None) self._processparam(*p) params[p[0]] = p[1] return params
def _processparam(self, name, value): """process a parameter, applying its effect if needed Parameter starting with a lower case letter are advisory and will be ignored when unknown. Those starting with an upper case letter are mandatory and will this function will raise a KeyError when unknown. Note: no option are currently supported. Any input will be either ignored or failing. """ if not name: raise ValueError('empty parameter name') if name[0] not in string.letters: raise ValueError('non letter first character: %r' % name) # Some logic will be later added here to try to process the option for # a dict of known parameter. if name[0].islower(): self.ui.debug("ignoring unknown parameter %r\n" % name) else: raise error.BundleValueError(params=(name, ))
def processbundle(repo, unbundler, transactiongetter=_notransaction): """This function process a bundle, apply effect to/from a repo It iterates over each part then searches for and uses the proper handling code to process the part. Parts are processed in order. This is very early version of this function that will be strongly reworked before final usage. Unknown Mandatory part will abort the process. """ op = bundleoperation(repo, transactiongetter) # todo: # - replace this is a init function soon. # - exception catching unbundler.params iterparts = unbundler.iterparts() part = None try: for part in iterparts: parttype = part.type # part key are matched lower case key = parttype.lower() try: handler = parthandlermapping.get(key) if handler is None: raise error.BundleValueError(parttype=key) op.ui.debug('found a handler for part %r\n' % parttype) unknownparams = part.mandatorykeys - handler.params if unknownparams: unknownparams = list(unknownparams) unknownparams.sort() raise error.BundleValueError(parttype=key, params=unknownparams) except error.BundleValueError, exc: if key != parttype: # mandatory parts raise op.ui.debug('ignoring unsupported advisory part %s\n' % exc) # consuming the part part.read() continue # handler is called outside the above try block so that we don't # risk catching KeyErrors from anything other than the # parthandlermapping lookup (any KeyError raised by handler() # itself represents a defect of a different variety). output = None if op.reply is not None: op.ui.pushbuffer(error=True) output = '' try: handler(op, part) finally: if output is not None: output = op.ui.popbuffer() if output: outpart = op.reply.newpart('b2x:output', data=output) outpart.addparam('in-reply-to', str(part.id), mandatory=False) part.read() except Exception, exc: if part is not None: # consume the bundle content part.read() for part in iterparts: # consume the bundle content part.read() # Small hack to let caller code distinguish exceptions from bundle2 # processing fron the ones from bundle1 processing. This is mostly # needed to handle different return codes to unbundle according to the # type of bundle. We should probably clean up or drop this return code # craziness in a future version. exc.duringunbundle2 = True raise