mercurial/bundle2.py
changeset 25318 64dd8f25fcf4
parent 25317 5a5b7046d00e
child 25319 c3ef4f3b8680
equal deleted inserted replaced
25317:5a5b7046d00e 25318:64dd8f25fcf4
   174 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
   174 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
   175 
   175 
   176 def outdebug(ui, message):
   176 def outdebug(ui, message):
   177     """debug regarding output stream (bundling)"""
   177     """debug regarding output stream (bundling)"""
   178     ui.debug('bundle2-output: %s\n' % message)
   178     ui.debug('bundle2-output: %s\n' % message)
       
   179 
       
   180 def indebug(ui, message):
       
   181     """debug on input stream (unbundling)"""
       
   182     ui.debug(message)
   179 
   183 
   180 def validateparttype(parttype):
   184 def validateparttype(parttype):
   181     """raise ValueError if a parttype contains invalid character"""
   185     """raise ValueError if a parttype contains invalid character"""
   182     if _parttypeforbidden.search(parttype):
   186     if _parttypeforbidden.search(parttype):
   183         raise ValueError(parttype)
   187         raise ValueError(parttype)
   344     try:
   348     try:
   345         try:
   349         try:
   346             handler = parthandlermapping.get(part.type)
   350             handler = parthandlermapping.get(part.type)
   347             if handler is None:
   351             if handler is None:
   348                 raise error.UnsupportedPartError(parttype=part.type)
   352                 raise error.UnsupportedPartError(parttype=part.type)
   349             op.ui.debug('found a handler for part %r\n' % part.type)
   353             indebug(op.ui, 'found a handler for part %r\n' % part.type)
   350             unknownparams = part.mandatorykeys - handler.params
   354             unknownparams = part.mandatorykeys - handler.params
   351             if unknownparams:
   355             if unknownparams:
   352                 unknownparams = list(unknownparams)
   356                 unknownparams = list(unknownparams)
   353                 unknownparams.sort()
   357                 unknownparams.sort()
   354                 raise error.UnsupportedPartError(parttype=part.type,
   358                 raise error.UnsupportedPartError(parttype=part.type,
   355                                                params=unknownparams)
   359                                                params=unknownparams)
   356         except error.UnsupportedPartError, exc:
   360         except error.UnsupportedPartError, exc:
   357             if part.mandatory: # mandatory parts
   361             if part.mandatory: # mandatory parts
   358                 raise
   362                 raise
   359             op.ui.debug('ignoring unsupported advisory part %s\n' % exc)
   363             indebug(op.ui, 'ignoring unsupported advisory part %s\n' % exc)
   360             return # skip to part processing
   364             return # skip to part processing
   361 
   365 
   362         # handler is called outside the above try block so that we don't
   366         # handler is called outside the above try block so that we don't
   363         # risk catching KeyErrors from anything other than the
   367         # risk catching KeyErrors from anything other than the
   364         # parthandlermapping lookup (any KeyError raised by handler()
   368         # parthandlermapping lookup (any KeyError raised by handler()
   557         raise util.Abort(_('not a Mercurial bundle'))
   561         raise util.Abort(_('not a Mercurial bundle'))
   558     unbundlerclass = formatmap.get(version)
   562     unbundlerclass = formatmap.get(version)
   559     if unbundlerclass is None:
   563     if unbundlerclass is None:
   560         raise util.Abort(_('unknown bundle version %s') % version)
   564         raise util.Abort(_('unknown bundle version %s') % version)
   561     unbundler = unbundlerclass(ui, fp)
   565     unbundler = unbundlerclass(ui, fp)
   562     ui.debug('start processing of %s stream\n' % header)
   566     indebug(ui, 'start processing of %s stream\n' % header)
   563     return unbundler
   567     return unbundler
   564 
   568 
   565 class unbundle20(unpackermixin):
   569 class unbundle20(unpackermixin):
   566     """interpret a bundle2 stream
   570     """interpret a bundle2 stream
   567 
   571 
   574         super(unbundle20, self).__init__(fp)
   578         super(unbundle20, self).__init__(fp)
   575 
   579 
   576     @util.propertycache
   580     @util.propertycache
   577     def params(self):
   581     def params(self):
   578         """dictionary of stream level parameters"""
   582         """dictionary of stream level parameters"""
   579         self.ui.debug('reading bundle2 stream parameters\n')
   583         indebug(self.ui, 'reading bundle2 stream parameters\n')
   580         params = {}
   584         params = {}
   581         paramssize = self._unpack(_fstreamparamsize)[0]
   585         paramssize = self._unpack(_fstreamparamsize)[0]
   582         if paramssize < 0:
   586         if paramssize < 0:
   583             raise error.BundleValueError('negative bundle param size: %i'
   587             raise error.BundleValueError('negative bundle param size: %i'
   584                                          % paramssize)
   588                                          % paramssize)
   607         if name[0] not in string.letters:
   611         if name[0] not in string.letters:
   608             raise ValueError('non letter first character: %r' % name)
   612             raise ValueError('non letter first character: %r' % name)
   609         # Some logic will be later added here to try to process the option for
   613         # Some logic will be later added here to try to process the option for
   610         # a dict of known parameter.
   614         # a dict of known parameter.
   611         if name[0].islower():
   615         if name[0].islower():
   612             self.ui.debug("ignoring unknown parameter %r\n" % name)
   616             indebug(self.ui, "ignoring unknown parameter %r\n" % name)
   613         else:
   617         else:
   614             raise error.UnsupportedPartError(params=(name,))
   618             raise error.UnsupportedPartError(params=(name,))
   615 
   619 
   616 
   620 
   617     def iterparts(self):
   621     def iterparts(self):
   618         """yield all parts contained in the stream"""
   622         """yield all parts contained in the stream"""
   619         # make sure param have been loaded
   623         # make sure param have been loaded
   620         self.params
   624         self.params
   621         self.ui.debug('start extraction of bundle2 parts\n')
   625         indebug(self.ui, 'start extraction of bundle2 parts\n')
   622         headerblock = self._readpartheader()
   626         headerblock = self._readpartheader()
   623         while headerblock is not None:
   627         while headerblock is not None:
   624             part = unbundlepart(self.ui, headerblock, self._fp)
   628             part = unbundlepart(self.ui, headerblock, self._fp)
   625             yield part
   629             yield part
   626             part.seek(0, 2)
   630             part.seek(0, 2)
   627             headerblock = self._readpartheader()
   631             headerblock = self._readpartheader()
   628         self.ui.debug('end of bundle2 stream\n')
   632         indebug(self.ui, 'end of bundle2 stream\n')
   629 
   633 
   630     def _readpartheader(self):
   634     def _readpartheader(self):
   631         """reads a part header size and return the bytes blob
   635         """reads a part header size and return the bytes blob
   632 
   636 
   633         returns None if empty"""
   637         returns None if empty"""
   634         headersize = self._unpack(_fpartheadersize)[0]
   638         headersize = self._unpack(_fpartheadersize)[0]
   635         if headersize < 0:
   639         if headersize < 0:
   636             raise error.BundleValueError('negative part header size: %i'
   640             raise error.BundleValueError('negative part header size: %i'
   637                                          % headersize)
   641                                          % headersize)
   638         self.ui.debug('part header size: %i\n' % headersize)
   642         indebug(self.ui, 'part header size: %i\n' % headersize)
   639         if headersize:
   643         if headersize:
   640             return self._readexact(headersize)
   644             return self._readexact(headersize)
   641         return None
   645         return None
   642 
   646 
   643     def compressed(self):
   647     def compressed(self):
   819         returns None if empty"""
   823         returns None if empty"""
   820         headersize = self._unpack(_fpartheadersize)[0]
   824         headersize = self._unpack(_fpartheadersize)[0]
   821         if headersize < 0:
   825         if headersize < 0:
   822             raise error.BundleValueError('negative part header size: %i'
   826             raise error.BundleValueError('negative part header size: %i'
   823                                          % headersize)
   827                                          % headersize)
   824         self.ui.debug('part header size: %i\n' % headersize)
   828         indebug(self.ui, 'part header size: %i\n' % headersize)
   825         if headersize:
   829         if headersize:
   826             return self._readexact(headersize)
   830             return self._readexact(headersize)
   827         return None
   831         return None
   828 
   832 
   829     def __call__(self):
   833     def __call__(self):
   830         self.ui.debug('bundle2 stream interruption, looking for a part.\n')
   834         indebug(self.ui, 'bundle2 stream interruption, looking for a part.\n')
   831         headerblock = self._readpartheader()
   835         headerblock = self._readpartheader()
   832         if headerblock is None:
   836         if headerblock is None:
   833             self.ui.debug('no part found during interruption.\n')
   837             indebug(self.ui, 'no part found during interruption.\n')
   834             return
   838             return
   835         part = unbundlepart(self.ui, headerblock, self._fp)
   839         part = unbundlepart(self.ui, headerblock, self._fp)
   836         op = interruptoperation(self.ui)
   840         op = interruptoperation(self.ui)
   837         _processpart(op, part)
   841         _processpart(op, part)
   838 
   842 
   912                    'Unknown chunk %d' % chunknum
   916                    'Unknown chunk %d' % chunknum
   913             super(unbundlepart, self).seek(self._chunkindex[chunknum][1])
   917             super(unbundlepart, self).seek(self._chunkindex[chunknum][1])
   914 
   918 
   915         pos = self._chunkindex[chunknum][0]
   919         pos = self._chunkindex[chunknum][0]
   916         payloadsize = self._unpack(_fpayloadsize)[0]
   920         payloadsize = self._unpack(_fpayloadsize)[0]
   917         self.ui.debug('payload chunk size: %i\n' % payloadsize)
   921         indebug(self.ui, 'payload chunk size: %i\n' % payloadsize)
   918         while payloadsize:
   922         while payloadsize:
   919             if payloadsize == flaginterrupt:
   923             if payloadsize == flaginterrupt:
   920                 # interruption detection, the handler will now read a
   924                 # interruption detection, the handler will now read a
   921                 # single part and process it.
   925                 # single part and process it.
   922                 interrupthandler(self.ui, self._fp)()
   926                 interrupthandler(self.ui, self._fp)()
   930                 if chunknum == len(self._chunkindex):
   934                 if chunknum == len(self._chunkindex):
   931                     self._chunkindex.append((pos,
   935                     self._chunkindex.append((pos,
   932                                              super(unbundlepart, self).tell()))
   936                                              super(unbundlepart, self).tell()))
   933                 yield result
   937                 yield result
   934             payloadsize = self._unpack(_fpayloadsize)[0]
   938             payloadsize = self._unpack(_fpayloadsize)[0]
   935             self.ui.debug('payload chunk size: %i\n' % payloadsize)
   939             indebug(self.ui, 'payload chunk size: %i\n' % payloadsize)
   936 
   940 
   937     def _findchunk(self, pos):
   941     def _findchunk(self, pos):
   938         '''for a given payload position, return a chunk number and offset'''
   942         '''for a given payload position, return a chunk number and offset'''
   939         for chunk, (ppos, fpos) in enumerate(self._chunkindex):
   943         for chunk, (ppos, fpos) in enumerate(self._chunkindex):
   940             if ppos == pos:
   944             if ppos == pos:
   945 
   949 
   946     def _readheader(self):
   950     def _readheader(self):
   947         """read the header and setup the object"""
   951         """read the header and setup the object"""
   948         typesize = self._unpackheader(_fparttypesize)[0]
   952         typesize = self._unpackheader(_fparttypesize)[0]
   949         self.type = self._fromheader(typesize)
   953         self.type = self._fromheader(typesize)
   950         self.ui.debug('part type: "%s"\n' % self.type)
   954         indebug(self.ui, 'part type: "%s"\n' % self.type)
   951         self.id = self._unpackheader(_fpartid)[0]
   955         self.id = self._unpackheader(_fpartid)[0]
   952         self.ui.debug('part id: "%s"\n' % self.id)
   956         indebug(self.ui, 'part id: "%s"\n' % self.id)
   953         # extract mandatory bit from type
   957         # extract mandatory bit from type
   954         self.mandatory = (self.type != self.type.lower())
   958         self.mandatory = (self.type != self.type.lower())
   955         self.type = self.type.lower()
   959         self.type = self.type.lower()
   956         ## reading parameters
   960         ## reading parameters
   957         # param count
   961         # param count
   958         mancount, advcount = self._unpackheader(_fpartparamcount)
   962         mancount, advcount = self._unpackheader(_fpartparamcount)
   959         self.ui.debug('part parameters: %i\n' % (mancount + advcount))
   963         indebug(self.ui, 'part parameters: %i\n' % (mancount + advcount))
   960         # param size
   964         # param size
   961         fparamsizes = _makefpartparamsizes(mancount + advcount)
   965         fparamsizes = _makefpartparamsizes(mancount + advcount)
   962         paramsizes = self._unpackheader(fparamsizes)
   966         paramsizes = self._unpackheader(fparamsizes)
   963         # make it a list of couple again
   967         # make it a list of couple again
   964         paramsizes = zip(paramsizes[::2], paramsizes[1::2])
   968         paramsizes = zip(paramsizes[::2], paramsizes[1::2])