# HG changeset patch # User Pierre-Yves David # Date 1491757747 -7200 # Node ID a02e773008f5c664c5da212910ddd344125b4b8b # Parent 1c398f7f4aa437a7c692025f0434c0564dbf72ff bundle2: move 'seek' and 'tell' methods off the unpackermixin class These methods are unrelated to unpacking. They are used internally by the 'unbundlepart' class only. So me move them there as private methods. In the same go, we clarify their internal role in the their docstring. diff -r 1c398f7f4aa4 -r a02e773008f5 mercurial/bundle2.py --- a/mercurial/bundle2.py Mon Apr 10 15:32:09 2017 -0700 +++ b/mercurial/bundle2.py Sun Apr 09 19:09:07 2017 +0200 @@ -617,8 +617,6 @@ def __init__(self, fp): self._fp = fp - self._seekable = (util.safehasattr(fp, 'seek') and - util.safehasattr(fp, 'tell')) def _unpack(self, format): """unpack this struct format from the stream @@ -641,25 +639,6 @@ Do not use it to implement higher-level logic or methods.""" return changegroup.readexactly(self._fp, size) - def seek(self, offset, whence=0): - """move the underlying file pointer""" - if self._seekable: - return self._fp.seek(offset, whence) - else: - raise NotImplementedError(_('File pointer is not seekable')) - - def tell(self): - """return the file offset, or None if file is not seekable""" - if self._seekable: - try: - return self._fp.tell() - except IOError as e: - if e.errno == errno.ESPIPE: - self._seekable = False - else: - raise - return None - def getunbundler(ui, fp, magicstring=None): """return a valid unbundler object for a given magicstring""" if magicstring is None: @@ -1111,6 +1090,8 @@ def __init__(self, ui, header, fp): super(unbundlepart, self).__init__(fp) + self._seekable = (util.safehasattr(fp, 'seek') and + util.safehasattr(fp, 'tell')) self.ui = ui # unbundle state attr self._headerdata = header @@ -1158,11 +1139,11 @@ '''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())) + self._chunkindex.append((0, self._tellfp())) else: assert chunknum < len(self._chunkindex), \ 'Unknown chunk %d' % chunknum - super(unbundlepart, self).seek(self._chunkindex[chunknum][1]) + self._seekfp(self._chunkindex[chunknum][1]) pos = self._chunkindex[chunknum][0] payloadsize = self._unpack(_fpayloadsize)[0] @@ -1180,8 +1161,7 @@ chunknum += 1 pos += payloadsize if chunknum == len(self._chunkindex): - self._chunkindex.append((pos, - super(unbundlepart, self).tell())) + self._chunkindex.append((pos, self._tellfp())) yield result payloadsize = self._unpack(_fpayloadsize)[0] indebug(self.ui, 'payload chunk size: %i' % payloadsize) @@ -1274,6 +1254,37 @@ raise error.Abort(_('Seek failed\n')) self._pos = newpos + def _seekfp(self, offset, whence=0): + """move the underlying file pointer + + This method is meant for internal usage by the bundle2 protocol only. + They directly manipulate the low level stream including bundle2 level + instruction. + + Do not use it to implement higher-level logic or methods.""" + if self._seekable: + return self._fp.seek(offset, whence) + else: + raise NotImplementedError(_('File pointer is not seekable')) + + def _tellfp(self): + """return the file offset, or None if file is not seekable + + This method is meant for internal usage by the bundle2 protocol only. + They directly manipulate the low level stream including bundle2 level + instruction. + + Do not use it to implement higher-level logic or methods.""" + if self._seekable: + try: + return self._fp.tell() + except IOError as e: + if e.errno == errno.ESPIPE: + self._seekable = False + else: + raise + return None + # These are only the static capabilities. # Check the 'getrepocaps' function for the rest. capabilities = {'HG20': (),