Mercurial > hg
comparison mercurial/revlog.py @ 39139:3730b779ed5b stable
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).
author | Boris Feld <boris.feld@octobus.net> |
---|---|
date | Wed, 15 Aug 2018 14:43:40 +0200 |
parents | 33ac6a72308a |
children | b95b48a55c36 |
comparison
equal
deleted
inserted
replaced
39021:7e023ce26c7f | 39139:3730b779ed5b |
---|---|
260 length = revlog.length | 260 length = revlog.length |
261 | 261 |
262 if endidx is None: | 262 if endidx is None: |
263 endidx = len(revs) | 263 endidx = len(revs) |
264 | 264 |
265 # Trim empty revs at the end, but never the very first revision of a chain | 265 # If we have a non-emtpy delta candidate, there are nothing to trim |
266 while endidx > 1 and endidx > startidx and length(revs[endidx - 1]) == 0: | 266 if revs[endidx - 1] < len(revlog): |
267 endidx -= 1 | 267 # Trim empty revs at the end, except the very first revision of a chain |
268 while (endidx > 1 | |
269 and endidx > startidx | |
270 and length(revs[endidx - 1]) == 0): | |
271 endidx -= 1 | |
268 | 272 |
269 return revs[startidx:endidx] | 273 return revs[startidx:endidx] |
270 | 274 |
271 def _segmentspan(revlog, revs): | 275 def _segmentspan(revlog, revs, deltainfo=None): |
272 """Get the byte span of a segment of revisions | 276 """Get the byte span of a segment of revisions |
273 | 277 |
274 revs is a sorted array of revision numbers | 278 revs is a sorted array of revision numbers |
275 | 279 |
276 >>> revlog = _testrevlog([ | 280 >>> revlog = _testrevlog([ |
292 >>> _segmentspan(revlog, [1, 3]) | 296 >>> _segmentspan(revlog, [1, 3]) |
293 7 | 297 7 |
294 """ | 298 """ |
295 if not revs: | 299 if not revs: |
296 return 0 | 300 return 0 |
297 return revlog.end(revs[-1]) - revlog.start(revs[0]) | 301 if deltainfo is not None and len(revlog) <= revs[-1]: |
302 if len(revs) == 1: | |
303 return deltainfo.deltalen | |
304 offset = revlog.end(len(revlog) - 1) | |
305 end = deltainfo.deltalen + offset | |
306 else: | |
307 end = revlog.end(revs[-1]) | |
308 return end - revlog.start(revs[0]) | |
298 | 309 |
299 def _slicechunk(revlog, revs, deltainfo=None, targetsize=None): | 310 def _slicechunk(revlog, revs, deltainfo=None, targetsize=None): |
300 """slice revs to reduce the amount of unrelated data to be read from disk. | 311 """slice revs to reduce the amount of unrelated data to be read from disk. |
301 | 312 |
302 ``revs`` is sliced into groups that should be read in one time. | 313 ``revs`` is sliced into groups that should be read in one time. |
524 | 535 |
525 if density >= targetdensity: | 536 if density >= targetdensity: |
526 yield revs | 537 yield revs |
527 return | 538 return |
528 | 539 |
529 if deltainfo is not None: | 540 if deltainfo is not None and deltainfo.deltalen: |
530 revs = list(revs) | 541 revs = list(revs) |
531 revs.append(nextrev) | 542 revs.append(nextrev) |
532 | 543 |
533 # Store the gaps in a heap to have them sorted by decreasing size | 544 # Store the gaps in a heap to have them sorted by decreasing size |
534 gapsheap = [] | 545 gapsheap = [] |
2442 deltachain = self._deltachain(base)[0] | 2453 deltachain = self._deltachain(base)[0] |
2443 else: | 2454 else: |
2444 deltachain = [] | 2455 deltachain = [] |
2445 | 2456 |
2446 chunks = _slicechunk(self, deltachain, deltainfo) | 2457 chunks = _slicechunk(self, deltachain, deltainfo) |
2447 distance = max(map(lambda revs:_segmentspan(self, revs), chunks)) | 2458 all_span = [_segmentspan(self, revs, deltainfo) for revs in chunks] |
2459 distance = max(all_span) | |
2448 else: | 2460 else: |
2449 distance = deltainfo.distance | 2461 distance = deltainfo.distance |
2450 | 2462 |
2451 textlen = revinfo.textlen | 2463 textlen = revinfo.textlen |
2452 defaultmax = textlen * 4 | 2464 defaultmax = textlen * 4 |