##// END OF EJS Templates
changegroup: port to emitrevisions() (issue5976)...
Gregory Szorc -
r39901:31b7e8e7 default
parent child Browse files
Show More
@@ -24,13 +24,13 b' from .thirdparty import ('
24 24 )
25 25
26 26 from . import (
27 dagop,
28 27 error,
29 28 match as matchmod,
30 29 mdiff,
31 30 phases,
32 31 pycompat,
33 32 repository,
33 revlog,
34 34 util,
35 35 )
36 36
@@ -536,18 +536,8 b' def _revisiondeltatochunks(delta, header'
536 536 yield prefix
537 537 yield data
538 538
539 def _sortnodesnormal(store, nodes):
540 """Sort nodes for changegroup generation and turn into revnums."""
541 # for generaldelta revlogs, we linearize the revs; this will both be
542 # much quicker and generate a much smaller bundle
543 if store._generaldelta:
544 revs = set(store.rev(n) for n in nodes)
545 return dagop.linearize(revs, store.parentrevs)
546 else:
547 return sorted([store.rev(n) for n in nodes])
548
549 539 def _sortnodesellipsis(store, nodes, cl, lookup):
550 """Sort nodes for changegroup generation and turn into revnums."""
540 """Sort nodes for changegroup generation."""
551 541 # Ellipses serving mode.
552 542 #
553 543 # In a perfect world, we'd generate better ellipsis-ified graphs
@@ -565,11 +555,11 b' def _sortnodesellipsis(store, nodes, cl,'
565 555 # changelog, so what we do is we sort the non-changelog histories
566 556 # by the order in which they are used by the changelog.
567 557 key = lambda n: cl.rev(lookup(n))
568 return [store.rev(n) for n in sorted(nodes, key=key)]
558 return sorted(nodes, key=key)
569 559
570 def _makenarrowdeltarequest(cl, store, ischangelog, rev, node, linkrev,
571 linknode, clrevtolocalrev, fullclnodes,
572 precomputedellipsis):
560 def _resolvenarrowrevisioninfo(cl, store, ischangelog, rev, linkrev,
561 linknode, clrevtolocalrev, fullclnodes,
562 precomputedellipsis):
573 563 linkparents = precomputedellipsis[linkrev]
574 564 def local(clrev):
575 565 """Turn a changelog revnum into a local revnum.
@@ -644,15 +634,7 b' def _makenarrowdeltarequest(cl, store, i'
644 634
645 635 p1node, p2node = store.node(p1), store.node(p2)
646 636
647 # TODO: try and actually send deltas for ellipsis data blocks
648 return revisiondeltarequest(
649 node=node,
650 p1node=p1node,
651 p2node=p2node,
652 linknode=linknode,
653 basenode=nullid,
654 ellipsis=True,
655 )
637 return p1node, p2node, linknode
656 638
657 639 def deltagroup(repo, store, nodes, ischangelog, lookup, forcedeltaparentprev,
658 640 topic=None,
@@ -668,87 +650,97 b' def deltagroup(repo, store, nodes, ischa'
668 650 if not nodes:
669 651 return
670 652
671 # We perform two passes over the revisions whose data we will emit.
672 #
673 # In the first pass, we obtain information about the deltas that will
674 # be generated. This involves computing linknodes and adjusting the
675 # request to take shallow fetching into account. The end result of
676 # this pass is a list of "request" objects stating which deltas
677 # to obtain.
678 #
679 # The second pass is simply resolving the requested deltas.
680
681 653 cl = repo.changelog
682 654
683 655 if ischangelog:
684 # Changelog doesn't benefit from reordering revisions. So send
685 # out revisions in store order.
686 # TODO the API would be cleaner if this were controlled by the
687 # store producing the deltas.
688 revs = sorted(cl.rev(n) for n in nodes)
656 # `hg log` shows changesets in storage order. To preserve order
657 # across clones, send out changesets in storage order.
658 nodesorder = 'storage'
689 659 elif ellipses:
690 revs = _sortnodesellipsis(store, nodes, cl, lookup)
660 nodes = _sortnodesellipsis(store, nodes, cl, lookup)
661 nodesorder = 'nodes'
691 662 else:
692 revs = _sortnodesnormal(store, nodes)
663 nodesorder = None
693 664
694 # In the first pass, collect info about the deltas we'll be
695 # generating.
696 requests = []
697
698 # Add the parent of the first rev.
699 revs.insert(0, store.parentrevs(revs[0])[0])
665 # Perform ellipses filtering and revision massaging. We do this before
666 # emitrevisions() because a) filtering out revisions creates less work
667 # for emitrevisions() b) dropping revisions would break emitrevisions()'s
668 # assumptions about delta choices and we would possibly send a delta
669 # referencing a missing base revision.
670 #
671 # Also, calling lookup() has side-effects with regards to populating
672 # data structures. If we don't call lookup() for each node or if we call
673 # lookup() after the first pass through each node, things can break -
674 # possibly intermittently depending on the python hash seed! For that
675 # reason, we store a mapping of all linknodes during the initial node
676 # pass rather than use lookup() on the output side.
677 if ellipses:
678 filtered = []
679 adjustedparents = {}
680 linknodes = {}
700 681
701 for i in pycompat.xrange(len(revs) - 1):
702 prev = revs[i]
703 curr = revs[i + 1]
704
705 node = store.node(curr)
706 linknode = lookup(node)
707 p1node, p2node = store.parents(node)
708
709 if ellipses:
682 for node in nodes:
683 rev = store.rev(node)
684 linknode = lookup(node)
710 685 linkrev = cl.rev(linknode)
711 clrevtolocalrev[linkrev] = curr
686 clrevtolocalrev[linkrev] = rev
712 687
713 # This is a node to send in full, because the changeset it
714 # corresponds to was a full changeset.
688 # If linknode is in fullclnodes, it means the corresponding
689 # changeset was a full changeset and is being sent unaltered.
715 690 if linknode in fullclnodes:
716 requests.append(revisiondeltarequest(
717 node=node,
718 p1node=p1node,
719 p2node=p2node,
720 linknode=linknode,
721 basenode=None,
722 ))
691 linknodes[node] = linknode
723 692
693 # If the corresponding changeset wasn't in the set computed
694 # as relevant to us, it should be dropped outright.
724 695 elif linkrev not in precomputedellipsis:
725 pass
696 continue
697
726 698 else:
727 requests.append(_makenarrowdeltarequest(
728 cl, store, ischangelog, curr, node, linkrev, linknode,
729 clrevtolocalrev, fullclnodes,
730 precomputedellipsis))
731 else:
732 requests.append(revisiondeltarequest(
733 node=node,
734 p1node=p1node,
735 p2node=p2node,
736 linknode=linknode,
737 basenode=store.node(prev) if forcedeltaparentprev else None,
738 ))
699 # We could probably do this later and avoid the dict
700 # holding state. But it likely doesn't matter.
701 p1node, p2node, linknode = _resolvenarrowrevisioninfo(
702 cl, store, ischangelog, rev, linkrev, linknode,
703 clrevtolocalrev, fullclnodes, precomputedellipsis)
704
705 adjustedparents[node] = (p1node, p2node)
706 linknodes[node] = linknode
707
708 filtered.append(node)
709
710 nodes = filtered
739 711
740 712 # We expect the first pass to be fast, so we only engage the progress
741 713 # meter for constructing the revision deltas.
742 714 progress = None
743 715 if topic is not None:
744 716 progress = repo.ui.makeprogress(topic, unit=_('chunks'),
745 total=len(requests))
717 total=len(nodes))
746 718
747 for i, delta in enumerate(store.emitrevisiondeltas(requests)):
719 revisions = store.emitrevisions(
720 nodes,
721 nodesorder=nodesorder,
722 revisiondata=True,
723 assumehaveparentrevisions=not ellipses,
724 deltaprevious=forcedeltaparentprev)
725
726 for i, revision in enumerate(revisions):
748 727 if progress:
749 728 progress.update(i + 1)
750 729
751 yield delta
730 if ellipses:
731 linknode = linknodes[revision.node]
732
733 if revision.node in adjustedparents:
734 p1node, p2node = adjustedparents[revision.node]
735 revision.p1node = p1node
736 revision.p2node = p2node
737 revision.flags |= revlog.REVIDX_ELLIPSIS
738
739 else:
740 linknode = lookup(revision.node)
741
742 revision.linknode = linknode
743 yield revision
752 744
753 745 if progress:
754 746 progress.complete()
General Comments 0
You need to be logged in to leave comments. Login now