[PATCH] bundle2.unpackermixin: control for underlying file descriptor

Eric Sumner ericsumner at fb.com
Wed Feb 4 00:30:24 UTC 2015


# HG changeset patch
# User Eric Sumner <ericsumner at fb.com>
# Date 1421274256 28800
#      Wed Jan 14 14:24:16 2015 -0800
# Node ID 6c20248d6cb42cbe43255070666e764e898ce311
# Parent  bc75f8750cde0150357b25919c945ce418f0e503
bundle2.unpackermixin: control for underlying file descriptor

This patch adds seek(), tell(), and close() implementations for unpackermixin
which forward to the file descriptor's implementation if possible.  A future
patch will use this to make bundle2.unbundlepart seekable, which will in turn
make it usable as a file descriptor for bundlerepo.

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -145,6 +145,7 @@
 preserve.
 """
 
+import errno
 import sys
 import util
 import struct
@@ -484,6 +485,8 @@
 
     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"""
@@ -494,6 +497,29 @@
         """read exactly <size> bytes from the stream"""
         return changegroup.readexactly(self._fp, size)
 
+    def seek(self, offset, whence):
+        """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, e:
+                if e.errno == errno.ESPIPE:
+                    self._seekable = False
+                else:
+                    raise
+        return None
+
+    def close(self):
+        """close underlying file"""
+        if util.safehasattr(self._fp, 'close'):
+            return self._fp.close()
 
 class unbundle20(unpackermixin):
     """interpret a bundle2 stream


More information about the Mercurial-devel mailing list