825 self.params = None |
825 self.params = None |
826 self.mandatorykeys = () |
826 self.mandatorykeys = () |
827 self._payloadstream = None |
827 self._payloadstream = None |
828 self._readheader() |
828 self._readheader() |
829 self._mandatory = None |
829 self._mandatory = None |
|
830 self._chunkindex = [] #(payload, file) position tuples for chunk starts |
830 |
831 |
831 def _fromheader(self, size): |
832 def _fromheader(self, size): |
832 """return the next <size> byte from the header""" |
833 """return the next <size> byte from the header""" |
833 offset = self._headeroffset |
834 offset = self._headeroffset |
834 data = self._headerdata[offset:(offset + size)] |
835 data = self._headerdata[offset:(offset + size)] |
850 # user friendly UI |
851 # user friendly UI |
851 self.params = dict(self.mandatoryparams) |
852 self.params = dict(self.mandatoryparams) |
852 self.params.update(dict(self.advisoryparams)) |
853 self.params.update(dict(self.advisoryparams)) |
853 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams) |
854 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams) |
854 |
855 |
855 def _payloadchunks(self): |
856 def _payloadchunks(self, chunknum=0): |
|
857 '''seek to specified chunk and start yielding data''' |
|
858 if len(self._chunkindex) == 0: |
|
859 assert chunknum == 0, 'Must start with chunk 0' |
|
860 self._chunkindex.append((0, super(unbundlepart, self).tell())) |
|
861 else: |
|
862 assert chunknum < len(self._chunkindex), \ |
|
863 'Unknown chunk %d' % chunknum |
|
864 super(unbundlepart, self).seek(self._chunkindex[chunknum][1]) |
|
865 |
|
866 pos = self._chunkindex[chunknum][0] |
856 payloadsize = self._unpack(_fpayloadsize)[0] |
867 payloadsize = self._unpack(_fpayloadsize)[0] |
857 self.ui.debug('payload chunk size: %i\n' % payloadsize) |
868 self.ui.debug('payload chunk size: %i\n' % payloadsize) |
858 while payloadsize: |
869 while payloadsize: |
859 if payloadsize == flaginterrupt: |
870 if payloadsize == flaginterrupt: |
860 # interruption detection, the handler will now read a |
871 # interruption detection, the handler will now read a |
862 interrupthandler(self.ui, self._fp)() |
873 interrupthandler(self.ui, self._fp)() |
863 elif payloadsize < 0: |
874 elif payloadsize < 0: |
864 msg = 'negative payload chunk size: %i' % payloadsize |
875 msg = 'negative payload chunk size: %i' % payloadsize |
865 raise error.BundleValueError(msg) |
876 raise error.BundleValueError(msg) |
866 else: |
877 else: |
867 yield self._readexact(payloadsize) |
878 result = self._readexact(payloadsize) |
|
879 chunknum += 1 |
|
880 pos += payloadsize |
|
881 if chunknum == len(self._chunkindex): |
|
882 self._chunkindex.append((pos, |
|
883 super(unbundlepart, self).tell())) |
|
884 yield result |
868 payloadsize = self._unpack(_fpayloadsize)[0] |
885 payloadsize = self._unpack(_fpayloadsize)[0] |
869 self.ui.debug('payload chunk size: %i\n' % payloadsize) |
886 self.ui.debug('payload chunk size: %i\n' % payloadsize) |
870 |
887 |
871 def _readheader(self): |
888 def _readheader(self): |
872 """read the header and setup the object""" |
889 """read the header and setup the object""" |