revlog: add a _datareadfp context manager for data access needs
The helper handles:
1) is there a file handle already open that we shall just reuse,
2) is the revlog inlined or not.
Using a context manager for all read access will help setting up file pointer
caching in later changesets.
--- a/mercurial/revlog.py Mon Feb 05 17:35:14 2018 +0100
+++ b/mercurial/revlog.py Mon Feb 05 17:57:29 2018 +0100
@@ -15,6 +15,7 @@
import binascii
import collections
+import contextlib
import errno
import hashlib
import heapq
@@ -694,6 +695,19 @@
"""file object for the revlog's data file"""
return self.opener(self.datafile, mode=mode)
+ @contextlib.contextmanager
+ def _datareadfp(self, existingfp=None):
+ """file object suitable to read data"""
+ if existingfp is not None:
+ yield existingfp
+ else:
+ if self._inline:
+ func = self._indexfp
+ else:
+ func = self._datafp
+ with func() as fp:
+ yield fp
+
def tip(self):
return self.node(len(self.index) - 2)
def __contains__(self, rev):
@@ -1502,15 +1516,6 @@
Returns a str or buffer of raw byte data.
"""
- if df is not None:
- closehandle = False
- else:
- if self._inline:
- df = self._indexfp()
- else:
- df = self._datafp()
- closehandle = True
-
# Cache data both forward and backward around the requested
# data, in a fixed size window. This helps speed up operations
# involving reading the revlog backwards.
@@ -1518,10 +1523,9 @@
realoffset = offset & ~(cachesize - 1)
reallength = (((offset + length + cachesize) & ~(cachesize - 1))
- realoffset)
- df.seek(realoffset)
- d = df.read(reallength)
- if closehandle:
- df.close()
+ with self._datareadfp(df) as df:
+ df.seek(realoffset)
+ d = df.read(reallength)
self._cachesegment(realoffset, d)
if offset != realoffset or reallength != length:
return util.buffer(d, offset - realoffset, length)