##// END OF EJS Templates
changegroup: pass sorted revisions into group() (API)...
Gregory Szorc -
r39018:037debbf default
parent child Browse files
Show More
@@ -523,6 +523,37 b' class revisiondelta(object):'
523 523 # Iterable of chunks holding raw delta data.
524 524 deltachunks = attr.ib()
525 525
526 def _sortnodesnormal(store, nodes, reorder):
527 """Sort nodes for changegroup generation and turn into revnums."""
528 # for generaldelta revlogs, we linearize the revs; this will both be
529 # much quicker and generate a much smaller bundle
530 if (store._generaldelta and reorder is None) or reorder:
531 dag = dagutil.revlogdag(store)
532 return dag.linearize(set(store.rev(n) for n in nodes))
533 else:
534 return sorted([store.rev(n) for n in nodes])
535
536 def _sortnodesellipsis(store, nodes, clnodetorev, lookup):
537 """Sort nodes for changegroup generation and turn into revnums."""
538 # Ellipses serving mode.
539 #
540 # In a perfect world, we'd generate better ellipsis-ified graphs
541 # for non-changelog revlogs. In practice, we haven't started doing
542 # that yet, so the resulting DAGs for the manifestlog and filelogs
543 # are actually full of bogus parentage on all the ellipsis
544 # nodes. This has the side effect that, while the contents are
545 # correct, the individual DAGs might be completely out of whack in
546 # a case like 882681bc3166 and its ancestors (back about 10
547 # revisions or so) in the main hg repo.
548 #
549 # The one invariant we *know* holds is that the new (potentially
550 # bogus) DAG shape will be valid if we order the nodes in the
551 # order that they're introduced in dramatis personae by the
552 # changelog, so what we do is we sort the non-changelog histories
553 # by the order in which they are used by the changelog.
554 key = lambda n: clnodetorev[lookup(n)]
555 return [store.rev(n) for n in sorted(nodes, key=key)]
556
526 557 class cgpacker(object):
527 558 def __init__(self, repo, filematcher, version, allowreorder,
528 559 deltaparentfn, builddeltaheader, manifestsend,
@@ -610,38 +641,7 b' class cgpacker(object):'
610 641
611 642 return closechunk()
612 643
613 # Extracted both for clarity and for overriding in extensions.
614 def _sortgroup(self, store, ischangelog, nodelist, lookup):
615 """Sort nodes for change group and turn them into revnums."""
616 # Ellipses serving mode.
617 #
618 # In a perfect world, we'd generate better ellipsis-ified graphs
619 # for non-changelog revlogs. In practice, we haven't started doing
620 # that yet, so the resulting DAGs for the manifestlog and filelogs
621 # are actually full of bogus parentage on all the ellipsis
622 # nodes. This has the side effect that, while the contents are
623 # correct, the individual DAGs might be completely out of whack in
624 # a case like 882681bc3166 and its ancestors (back about 10
625 # revisions or so) in the main hg repo.
626 #
627 # The one invariant we *know* holds is that the new (potentially
628 # bogus) DAG shape will be valid if we order the nodes in the
629 # order that they're introduced in dramatis personae by the
630 # changelog, so what we do is we sort the non-changelog histories
631 # by the order in which they are used by the changelog.
632 if self._ellipses and not ischangelog:
633 key = lambda n: self._clnodetorev[lookup(n)]
634 return [store.rev(n) for n in sorted(nodelist, key=key)]
635
636 # for generaldelta revlogs, we linearize the revs; this will both be
637 # much quicker and generate a much smaller bundle
638 if (store._generaldelta and self._reorder is None) or self._reorder:
639 dag = dagutil.revlogdag(store)
640 return dag.linearize(set(store.rev(n) for n in nodelist))
641 else:
642 return sorted([store.rev(n) for n in nodelist])
643
644 def group(self, nodelist, store, ischangelog, lookup, units=None):
644 def group(self, revs, store, ischangelog, lookup, units=None):
645 645 """Calculate a delta group, yielding a sequence of changegroup chunks
646 646 (strings).
647 647
@@ -656,12 +656,10 b' class cgpacker(object):'
656 656 the type of revlog that is touched (changelog, manifest, etc.).
657 657 """
658 658 # if we don't have any revisions touched by these changesets, bail
659 if len(nodelist) == 0:
659 if len(revs) == 0:
660 660 yield self._close()
661 661 return
662 662
663 revs = self._sortgroup(store, ischangelog, nodelist, lookup)
664
665 663 # add the parent of the first rev
666 664 p = store.parentrevs(revs[0])[0]
667 665 revs.insert(0, p)
@@ -693,20 +691,17 b' class cgpacker(object):'
693 691 rr, rl = store.rev, store.linkrev
694 692 return [n for n in missing if rl(rr(n)) not in commonrevs]
695 693
696 def _packmanifests(self, dir, mfnodes, lookuplinknode):
694 def _packmanifests(self, dir, dirlog, revs, lookuplinknode):
697 695 """Pack manifests into a changegroup stream.
698 696
699 697 Encodes the directory name in the output so multiple manifests
700 698 can be sent. Multiple manifests is not supported by cg1 and cg2.
701 699 """
702
703 700 if dir:
704 701 assert self.version == b'03'
705 702 yield _fileheader(dir)
706 703
707 # TODO violates storage abstractions by assuming revlogs.
708 dirlog = self._repo.manifestlog._revlog.dirlog(dir)
709 for chunk in self.group(mfnodes, dirlog, False, lookuplinknode,
704 for chunk in self.group(revs, dirlog, False, lookuplinknode,
710 705 units=_('manifests')):
711 706 yield chunk
712 707
@@ -850,13 +845,17 b' class cgpacker(object):'
850 845
851 846 return x
852 847
848 # Changelog doesn't benefit from reordering revisions. So send out
849 # revisions in store order.
850 revs = sorted(cl.rev(n) for n in nodes)
851
853 852 state = {
854 853 'clrevorder': clrevorder,
855 854 'mfs': mfs,
856 855 'changedfiles': changedfiles,
857 856 }
858 857
859 gen = self.group(nodes, cl, True, lookupcl, units=_('changesets'))
858 gen = self.group(revs, cl, True, lookupcl, units=_('changesets'))
860 859
861 860 return state, gen
862 861
@@ -917,10 +916,19 b' class cgpacker(object):'
917 916 size = 0
918 917 while tmfnodes:
919 918 dir, nodes = tmfnodes.popitem()
920 prunednodes = self._prune(dirlog(dir), nodes, commonrevs)
919 store = dirlog(dir)
920 prunednodes = self._prune(store, nodes, commonrevs)
921 921 if not dir or prunednodes:
922 for x in self._packmanifests(dir, prunednodes,
923 makelookupmflinknode(dir, nodes)):
922 lookupfn = makelookupmflinknode(dir, nodes)
923
924 if self._ellipses:
925 revs = _sortnodesellipsis(store, prunednodes,
926 self._clnodetorev, lookupfn)
927 else:
928 revs = _sortnodesnormal(store, prunednodes,
929 self._reorder)
930
931 for x in self._packmanifests(dir, store, revs, lookupfn):
924 932 size += len(x)
925 933 yield x
926 934 self._verbosenote(_('%8.i (manifests)\n') % size)
@@ -981,12 +989,18 b' class cgpacker(object):'
981 989
982 990 filenodes = self._prune(filerevlog, linkrevnodes, commonrevs)
983 991 if filenodes:
992 if self._ellipses:
993 revs = _sortnodesellipsis(filerevlog, filenodes,
994 self._clnodetorev, lookupfilelog)
995 else:
996 revs = _sortnodesnormal(filerevlog, filenodes,
997 self._reorder)
998
984 999 progress.update(i + 1, item=fname)
985 1000 h = _fileheader(fname)
986 1001 size = len(h)
987 1002 yield h
988 for chunk in self.group(filenodes, filerevlog, False,
989 lookupfilelog):
1003 for chunk in self.group(revs, filerevlog, False, lookupfilelog):
990 1004 size += len(chunk)
991 1005 yield chunk
992 1006 self._verbosenote(_('%8.i %s\n') % (size, fname))
General Comments 0
You need to be logged in to leave comments. Login now