482 class unpackermixin(object): |
483 class unpackermixin(object): |
483 """A mixin to extract bytes and struct data from a stream""" |
484 """A mixin to extract bytes and struct data from a stream""" |
484 |
485 |
485 def __init__(self, fp): |
486 def __init__(self, fp): |
486 self._fp = fp |
487 self._fp = fp |
|
488 self._seekable = (util.safehasattr(fp, 'seek') and |
|
489 util.safehasattr(fp, 'tell')) |
487 |
490 |
488 def _unpack(self, format): |
491 def _unpack(self, format): |
489 """unpack this struct format from the stream""" |
492 """unpack this struct format from the stream""" |
490 data = self._readexact(struct.calcsize(format)) |
493 data = self._readexact(struct.calcsize(format)) |
491 return _unpack(format, data) |
494 return _unpack(format, data) |
492 |
495 |
493 def _readexact(self, size): |
496 def _readexact(self, size): |
494 """read exactly <size> bytes from the stream""" |
497 """read exactly <size> bytes from the stream""" |
495 return changegroup.readexactly(self._fp, size) |
498 return changegroup.readexactly(self._fp, size) |
496 |
499 |
|
500 def seek(self, offset, whence): |
|
501 """move the underlying file pointer""" |
|
502 if self._seekable: |
|
503 return self._fp.seek(offset, whence) |
|
504 else: |
|
505 raise NotImplementedError(_('File pointer is not seekable')) |
|
506 |
|
507 def tell(self): |
|
508 """return the file offset, or None if file is not seekable""" |
|
509 if self._seekable: |
|
510 try: |
|
511 return self._fp.tell() |
|
512 except IOError, e: |
|
513 if e.errno == errno.ESPIPE: |
|
514 self._seekable = False |
|
515 else: |
|
516 raise |
|
517 return None |
|
518 |
|
519 def close(self): |
|
520 """close underlying file""" |
|
521 if util.safehasattr(self._fp, 'close'): |
|
522 return self._fp.close() |
497 |
523 |
498 class unbundle20(unpackermixin): |
524 class unbundle20(unpackermixin): |
499 """interpret a bundle2 stream |
525 """interpret a bundle2 stream |
500 |
526 |
501 This class is fed with a binary stream and yields parts through its |
527 This class is fed with a binary stream and yields parts through its |