248 previdx = idx |
251 previdx = idx |
249 |
252 |
250 chunk = _trimchunk(revlog, revs, previdx) |
253 chunk = _trimchunk(revlog, revs, previdx) |
251 if chunk: |
254 if chunk: |
252 yield chunk |
255 yield chunk |
|
256 |
|
257 @attr.s(slots=True, frozen=True) |
|
258 class _deltainfo(object): |
|
259 distance = attr.ib() |
|
260 deltalen = attr.ib() |
|
261 data = attr.ib() |
|
262 base = attr.ib() |
|
263 chainbase = attr.ib() |
|
264 chainlen = attr.ib() |
|
265 compresseddeltalen = attr.ib() |
253 |
266 |
254 # index v0: |
267 # index v0: |
255 # 4 bytes: offset |
268 # 4 bytes: offset |
256 # 4 bytes: compressed length |
269 # 4 bytes: compressed length |
257 # 4 bytes: base rev |
270 # 4 bytes: base rev |
1817 except KeyError: |
1830 except KeyError: |
1818 raise RevlogError(_('unknown compression type %r') % t) |
1831 raise RevlogError(_('unknown compression type %r') % t) |
1819 |
1832 |
1820 return compressor.decompress(data) |
1833 return compressor.decompress(data) |
1821 |
1834 |
1822 def _isgooddelta(self, d, textlen): |
1835 def _isgooddeltainfo(self, d, textlen): |
1823 """Returns True if the given delta is good. Good means that it is within |
1836 """Returns True if the given delta is good. Good means that it is within |
1824 the disk span, disk size, and chain length bounds that we know to be |
1837 the disk span, disk size, and chain length bounds that we know to be |
1825 performant.""" |
1838 performant.""" |
1826 if d is None: |
1839 if d is None: |
1827 return False |
1840 return False |
1828 |
1841 |
1829 # - 'dist' is the distance from the base revision -- bounding it limits |
1842 # - 'd.distance' is the distance from the base revision -- bounding it |
1830 # the amount of I/O we need to do. |
1843 # limits the amount of I/O we need to do. |
1831 # - 'compresseddeltalen' is the sum of the total size of deltas we need |
1844 # - 'd.compresseddeltalen' is the sum of the total size of deltas we |
1832 # to apply -- bounding it limits the amount of CPU we consume. |
1845 # need to apply -- bounding it limits the amount of CPU we consume. |
1833 dist, l, data, base, chainbase, chainlen, compresseddeltalen = d |
|
1834 |
1846 |
1835 defaultmax = textlen * 4 |
1847 defaultmax = textlen * 4 |
1836 maxdist = self._maxdeltachainspan |
1848 maxdist = self._maxdeltachainspan |
1837 if not maxdist: |
1849 if not maxdist: |
1838 maxdist = dist # ensure the conditional pass |
1850 maxdist = d.distance # ensure the conditional pass |
1839 maxdist = max(maxdist, defaultmax) |
1851 maxdist = max(maxdist, defaultmax) |
1840 if (dist > maxdist or l > textlen or |
1852 if (d.distance > maxdist or d.deltalen > textlen or |
1841 compresseddeltalen > textlen * 2 or |
1853 d.compresseddeltalen > textlen * 2 or |
1842 (self._maxchainlen and chainlen > self._maxchainlen)): |
1854 (self._maxchainlen and d.chainlen > self._maxchainlen)): |
1843 return False |
1855 return False |
1844 |
1856 |
1845 return True |
1857 return True |
1846 |
1858 |
1847 def _getcandidaterevs(self, p1, p2, cachedelta): |
1859 def _getcandidaterevs(self, p1, p2, cachedelta): |
1921 # must pass the censored index flag to add censored revisions |
1933 # must pass the censored index flag to add censored revisions |
1922 if not flags & REVIDX_ISCENSORED: |
1934 if not flags & REVIDX_ISCENSORED: |
1923 raise |
1935 raise |
1924 return btext[0] |
1936 return btext[0] |
1925 |
1937 |
1926 def _builddelta(self, node, rev, p1, p2, btext, cachedelta, fh, flags): |
1938 def _builddeltainfo(self, node, rev, p1, p2, btext, cachedelta, fh, flags): |
1927 # can we use the cached delta? |
1939 # can we use the cached delta? |
1928 if cachedelta and cachedelta[0] == rev: |
1940 if cachedelta and cachedelta[0] == rev: |
1929 delta = cachedelta[1] |
1941 delta = cachedelta[1] |
1930 else: |
1942 else: |
1931 t = self._buildtext(node, p1, p2, btext, cachedelta, fh, flags) |
1943 t = self._buildtext(node, p1, p2, btext, cachedelta, fh, flags) |
1947 else: |
1959 else: |
1948 base = chainbase |
1960 base = chainbase |
1949 chainlen, compresseddeltalen = self._chaininfo(rev) |
1961 chainlen, compresseddeltalen = self._chaininfo(rev) |
1950 chainlen += 1 |
1962 chainlen += 1 |
1951 compresseddeltalen += deltalen |
1963 compresseddeltalen += deltalen |
1952 return (dist, deltalen, (header, data), base, |
1964 return _deltainfo(dist, deltalen, (header, data), base, |
1953 chainbase, chainlen, compresseddeltalen) |
1965 chainbase, chainlen, compresseddeltalen) |
1954 |
1966 |
1955 def _addrevision(self, node, rawtext, transaction, link, p1, p2, flags, |
1967 def _addrevision(self, node, rawtext, transaction, link, p1, p2, flags, |
1956 cachedelta, ifh, dfh, alwayscache=False): |
1968 cachedelta, ifh, dfh, alwayscache=False): |
1957 """internal function to add revisions to the log |
1969 """internal function to add revisions to the log |
1958 |
1970 |
1993 textlen = len(rawtext) |
2005 textlen = len(rawtext) |
1994 |
2006 |
1995 for candidaterevs in self._getcandidaterevs(p1, p2, cachedelta): |
2007 for candidaterevs in self._getcandidaterevs(p1, p2, cachedelta): |
1996 nominateddeltas = [] |
2008 nominateddeltas = [] |
1997 for candidaterev in candidaterevs: |
2009 for candidaterev in candidaterevs: |
1998 candidatedelta = self._builddelta(node, candidaterev, p1, p2, |
2010 candidatedelta = self._builddeltainfo(node, candidaterev, p1, |
1999 btext, cachedelta, fh, |
2011 p2, btext, cachedelta, |
2000 flags) |
2012 fh, flags) |
2001 if self._isgooddelta(candidatedelta, textlen): |
2013 if self._isgooddeltainfo(candidatedelta, textlen): |
2002 nominateddeltas.append(candidatedelta) |
2014 nominateddeltas.append(candidatedelta) |
2003 if nominateddeltas: |
2015 if nominateddeltas: |
2004 delta = min(nominateddeltas, key=lambda x: x[1]) |
2016 deltainfo = min(nominateddeltas, key=lambda x: x.deltalen) |
2005 break |
2017 break |
2006 |
2018 |
2007 if delta is not None: |
2019 if deltainfo is not None: |
2008 dist, l, data, base, chainbase, chainlen, compresseddeltalen = delta |
2020 base = deltainfo.base |
|
2021 chainbase = deltainfo.chainbase |
|
2022 data = deltainfo.data |
|
2023 l = deltainfo.deltalen |
2009 else: |
2024 else: |
2010 rawtext = self._buildtext(node, p1, p2, btext, cachedelta, fh, |
2025 rawtext = self._buildtext(node, p1, p2, btext, cachedelta, fh, |
2011 flags) |
2026 flags) |
2012 data = self.compress(rawtext) |
2027 data = self.compress(rawtext) |
2013 l = len(data[1]) + len(data[0]) |
2028 l = len(data[1]) + len(data[0]) |