diff -r a2d11d23bb25 -r 01e29e885600 mercurial/util.py --- a/mercurial/util.py Mon Feb 05 15:03:51 2018 +0100 +++ b/mercurial/util.py Wed Feb 21 13:41:20 2018 -0800 @@ -1980,6 +1980,35 @@ limit -= len(s) yield s +class cappedreader(object): + """A file object proxy that allows reading up to N bytes. + + Given a source file object, instances of this type allow reading up to + N bytes from that source file object. Attempts to read past the allowed + limit are treated as EOF. + + It is assumed that I/O is not performed on the original file object + in addition to I/O that is performed by this instance. If there is, + state tracking will get out of sync and unexpected results will ensue. + """ + def __init__(self, fh, limit): + """Allow reading up to bytes from .""" + self._fh = fh + self._left = limit + + def read(self, n=-1): + if not self._left: + return b'' + + if n < 0: + n = self._left + + data = self._fh.read(min(n, self._left)) + self._left -= len(data) + assert self._left >= 0 + + return data + def makedate(timestamp=None): '''Return a unix timestamp (or the current time) as a (unixtime, offset) tuple based off the local timezone.'''