[PATCH STABLE] sparse-revlog: fix delta validity computation
Gregory Szorc
gregory.szorc at gmail.com
Fri Aug 17 18:50:00 EDT 2018
On Thu, Aug 16, 2018 at 2:01 AM, Boris Feld <boris.feld at octobus.net> wrote:
> # HG changeset patch
> # User Boris Feld <boris.feld at octobus.net>
> # Date 1534337020 -7200
> # Wed Aug 15 14:43:40 2018 +0200
> # Branch stable
> # Node ID 1b78bebb7a8793b4b858d335b11f4deaf57dd128
> # Parent 7e023ce26c7f5e800c778fb4ff76c6d7726666b3
> # EXP-Topic fix-sparse
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r
> 1b78bebb7a87
> sparse-revlog: fix delta validity computation
>
> When considering the validity of a delta with sparse-revlog, we check the
> size
> of the largest read. To do so, we use some regular logic with the extra
> delta
> information. Some of this logic was not handling this extra delta properly,
> confusing it with "nullrev". This confusion with nullrev lead to wrong
> results
> for this computation but preventing a crash.
>
> Changeset 781b2720d2ac on default revealed this error, crashing. This
> changeset fixes the logic on stable so that the computation is correct (and
> the crash is averted).
>
> The fix is made on stable as this will impact 4.7 clients interacting with
> sparse-revlog repositories (eg: created by later version).
>
Queued for stable.
>
> diff --git a/mercurial/revlog.py b/mercurial/revlog.py
> --- a/mercurial/revlog.py
> +++ b/mercurial/revlog.py
> @@ -262,13 +262,17 @@ def _trimchunk(revlog, revs, startidx, e
> if endidx is None:
> endidx = len(revs)
>
> - # Trim empty revs at the end, but never the very first revision of a
> chain
> - while endidx > 1 and endidx > startidx and length(revs[endidx - 1])
> == 0:
> - endidx -= 1
> + # If we have a non-emtpy delta candidate, there are nothing to trim
> + if revs[endidx - 1] < len(revlog):
> + # Trim empty revs at the end, except the very first revision of a
> chain
> + while (endidx > 1
> + and endidx > startidx
> + and length(revs[endidx - 1]) == 0):
> + endidx -= 1
>
> return revs[startidx:endidx]
>
> -def _segmentspan(revlog, revs):
> +def _segmentspan(revlog, revs, deltainfo=None):
> """Get the byte span of a segment of revisions
>
> revs is a sorted array of revision numbers
> @@ -294,7 +298,14 @@ def _segmentspan(revlog, revs):
> """
> if not revs:
> return 0
> - return revlog.end(revs[-1]) - revlog.start(revs[0])
> + if deltainfo is not None and len(revlog) <= revs[-1]:
> + if len(revs) == 1:
> + return deltainfo.deltalen
> + offset = revlog.end(len(revlog) - 1)
> + end = deltainfo.deltalen + offset
> + else:
> + end = revlog.end(revs[-1])
> + return end - revlog.start(revs[0])
>
> def _slicechunk(revlog, revs, deltainfo=None, targetsize=None):
> """slice revs to reduce the amount of unrelated data to be read from
> disk.
> @@ -526,7 +537,7 @@ def _slicechunktodensity(revlog, revs, d
> yield revs
> return
>
> - if deltainfo is not None:
> + if deltainfo is not None and deltainfo.deltalen:
> revs = list(revs)
> revs.append(nextrev)
>
> @@ -2444,7 +2455,8 @@ class revlog(object):
> deltachain = []
>
> chunks = _slicechunk(self, deltachain, deltainfo)
> - distance = max(map(lambda revs:_segmentspan(self, revs),
> chunks))
> + all_span = [_segmentspan(self, revs, deltainfo) for revs in
> chunks]
> + distance = max(all_span)
> else:
> distance = deltainfo.distance
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20180817/ddc5c408/attachment.html>
More information about the Mercurial-devel
mailing list