comparison mercurial/changegroup.py @ 34291:1db9abf407c5

revlog: add revmap back to revlog.addgroup The recent c8b6ed51386b patch removed the linkmapper argument from addgroup, as part of trying to make addgroup more agnostic from the changegroup format. It turns out that the changegroup can't resolve linkrevs while iterating over the deltas, because applying the deltas might affect the linkrev resolution. For example, when applying a series of changelog entries, the linkmapper just returns len(cl). If we're iterating over the deltas without applying them to the changelog, this results in incorrect linkrevs. This was caught by the hgsql extension, which reads the revisions before applying them. The fix is to return linknodes as part of the delta iterator, and let the consumer choose what to do. Differential Revision: https://phab.mercurial-scm.org/D730
author Durham Goode <durham@fb.com>
date Wed, 20 Sep 2017 09:22:22 -0700
parents 2844c4bd5a39
children 05131c963767
comparison
equal deleted inserted replaced
34290:4f969b9e0cf5 34291:1db9abf407c5
243 # no need to check for empty manifest group here: 243 # no need to check for empty manifest group here:
244 # if the result of the merge of 1 and 2 is the same in 3 and 4, 244 # if the result of the merge of 1 and 2 is the same in 3 and 4,
245 # no new manifest will be created and the manifest group will 245 # no new manifest will be created and the manifest group will
246 # be empty during the pull 246 # be empty during the pull
247 self.manifestheader() 247 self.manifestheader()
248 deltas = self.deltaiter(revmap) 248 deltas = self.deltaiter()
249 repo.manifestlog._revlog.addgroup(deltas, trp) 249 repo.manifestlog._revlog.addgroup(deltas, revmap, trp)
250 repo.ui.progress(_('manifests'), None) 250 repo.ui.progress(_('manifests'), None)
251 self.callback = None 251 self.callback = None
252 252
253 def apply(self, repo, tr, srctype, url, targetphase=phases.draft, 253 def apply(self, repo, tr, srctype, url, targetphase=phases.draft,
254 expectedtotal=None): 254 expectedtotal=None):
306 efiles = set() 306 efiles = set()
307 def onchangelog(cl, node): 307 def onchangelog(cl, node):
308 efiles.update(cl.readfiles(node)) 308 efiles.update(cl.readfiles(node))
309 309
310 self.changelogheader() 310 self.changelogheader()
311 deltas = self.deltaiter(csmap) 311 deltas = self.deltaiter()
312 cgnodes = cl.addgroup(deltas, trp, addrevisioncb=onchangelog) 312 cgnodes = cl.addgroup(deltas, csmap, trp, addrevisioncb=onchangelog)
313 efiles = len(efiles) 313 efiles = len(efiles)
314 314
315 if not cgnodes: 315 if not cgnodes:
316 repo.ui.develwarn('applied empty changegroup', 316 repo.ui.develwarn('applied empty changegroup',
317 config='empty-changegroup') 317 config='empty-changegroup')
428 ret = deltaheads - 1 428 ret = deltaheads - 1
429 else: 429 else:
430 ret = deltaheads + 1 430 ret = deltaheads + 1
431 return ret 431 return ret
432 432
433 def deltaiter(self, linkmapper): 433 def deltaiter(self):
434 """ 434 """
435 returns an iterator of the deltas in this changegroup 435 returns an iterator of the deltas in this changegroup
436 436
437 Useful for passing to the underlying storage system to be stored. 437 Useful for passing to the underlying storage system to be stored.
438 """ 438 """
444 cs = chunkdata['cs'] 444 cs = chunkdata['cs']
445 deltabase = chunkdata['deltabase'] 445 deltabase = chunkdata['deltabase']
446 delta = chunkdata['delta'] 446 delta = chunkdata['delta']
447 flags = chunkdata['flags'] 447 flags = chunkdata['flags']
448 448
449 link = linkmapper(cs)
450 chain = node 449 chain = node
451 450
452 yield (node, p1, p2, link, deltabase, delta, flags) 451 yield (node, p1, p2, cs, deltabase, delta, flags)
453 452
454 class cg2unpacker(cg1unpacker): 453 class cg2unpacker(cg1unpacker):
455 """Unpacker for cg2 streams. 454 """Unpacker for cg2 streams.
456 455
457 cg2 streams add support for generaldelta, so the delta header 456 cg2 streams add support for generaldelta, so the delta header
489 for chunkdata in iter(self.filelogheader, {}): 488 for chunkdata in iter(self.filelogheader, {}):
490 # If we get here, there are directory manifests in the changegroup 489 # If we get here, there are directory manifests in the changegroup
491 d = chunkdata["filename"] 490 d = chunkdata["filename"]
492 repo.ui.debug("adding %s revisions\n" % d) 491 repo.ui.debug("adding %s revisions\n" % d)
493 dirlog = repo.manifestlog._revlog.dirlog(d) 492 dirlog = repo.manifestlog._revlog.dirlog(d)
494 deltas = self.deltaiter(revmap) 493 deltas = self.deltaiter()
495 if not dirlog.addgroup(deltas, trp): 494 if not dirlog.addgroup(deltas, revmap, trp):
496 raise error.Abort(_("received dir revlog group is empty")) 495 raise error.Abort(_("received dir revlog group is empty"))
497 496
498 class headerlessfixup(object): 497 class headerlessfixup(object):
499 def __init__(self, fh, h): 498 def __init__(self, fh, h):
500 self._h = h 499 self._h = h
981 repo.ui.progress(_('files'), files, unit=_('files'), 980 repo.ui.progress(_('files'), files, unit=_('files'),
982 total=expectedfiles) 981 total=expectedfiles)
983 fl = repo.file(f) 982 fl = repo.file(f)
984 o = len(fl) 983 o = len(fl)
985 try: 984 try:
986 deltas = source.deltaiter(revmap) 985 deltas = source.deltaiter()
987 if not fl.addgroup(deltas, trp): 986 if not fl.addgroup(deltas, revmap, trp):
988 raise error.Abort(_("received file revlog group is empty")) 987 raise error.Abort(_("received file revlog group is empty"))
989 except error.CensoredBaseError as e: 988 except error.CensoredBaseError as e:
990 raise error.Abort(_("received delta base is censored: %s") % e) 989 raise error.Abort(_("received delta base is censored: %s") % e)
991 revisions += len(fl) - o 990 revisions += len(fl) - o
992 if f in needfiles: 991 if f in needfiles: