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