##// 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 # Iterable of chunks holding raw delta data.
523 # Iterable of chunks holding raw delta data.
524 deltachunks = attr.ib()
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 class cgpacker(object):
557 class cgpacker(object):
527 def __init__(self, repo, filematcher, version, allowreorder,
558 def __init__(self, repo, filematcher, version, allowreorder,
528 deltaparentfn, builddeltaheader, manifestsend,
559 deltaparentfn, builddeltaheader, manifestsend,
@@ -610,38 +641,7 b' class cgpacker(object):'
610
641
611 return closechunk()
642 return closechunk()
612
643
613 # Extracted both for clarity and for overriding in extensions.
644 def group(self, revs, store, ischangelog, lookup, units=None):
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):
645 """Calculate a delta group, yielding a sequence of changegroup chunks
645 """Calculate a delta group, yielding a sequence of changegroup chunks
646 (strings).
646 (strings).
647
647
@@ -656,12 +656,10 b' class cgpacker(object):'
656 the type of revlog that is touched (changelog, manifest, etc.).
656 the type of revlog that is touched (changelog, manifest, etc.).
657 """
657 """
658 # if we don't have any revisions touched by these changesets, bail
658 # if we don't have any revisions touched by these changesets, bail
659 if len(nodelist) == 0:
659 if len(revs) == 0:
660 yield self._close()
660 yield self._close()
661 return
661 return
662
662
663 revs = self._sortgroup(store, ischangelog, nodelist, lookup)
664
665 # add the parent of the first rev
663 # add the parent of the first rev
666 p = store.parentrevs(revs[0])[0]
664 p = store.parentrevs(revs[0])[0]
667 revs.insert(0, p)
665 revs.insert(0, p)
@@ -693,20 +691,17 b' class cgpacker(object):'
693 rr, rl = store.rev, store.linkrev
691 rr, rl = store.rev, store.linkrev
694 return [n for n in missing if rl(rr(n)) not in commonrevs]
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 """Pack manifests into a changegroup stream.
695 """Pack manifests into a changegroup stream.
698
696
699 Encodes the directory name in the output so multiple manifests
697 Encodes the directory name in the output so multiple manifests
700 can be sent. Multiple manifests is not supported by cg1 and cg2.
698 can be sent. Multiple manifests is not supported by cg1 and cg2.
701 """
699 """
702
703 if dir:
700 if dir:
704 assert self.version == b'03'
701 assert self.version == b'03'
705 yield _fileheader(dir)
702 yield _fileheader(dir)
706
703
707 # TODO violates storage abstractions by assuming revlogs.
704 for chunk in self.group(revs, dirlog, False, lookuplinknode,
708 dirlog = self._repo.manifestlog._revlog.dirlog(dir)
709 for chunk in self.group(mfnodes, dirlog, False, lookuplinknode,
710 units=_('manifests')):
705 units=_('manifests')):
711 yield chunk
706 yield chunk
712
707
@@ -850,13 +845,17 b' class cgpacker(object):'
850
845
851 return x
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 state = {
852 state = {
854 'clrevorder': clrevorder,
853 'clrevorder': clrevorder,
855 'mfs': mfs,
854 'mfs': mfs,
856 'changedfiles': changedfiles,
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 return state, gen
860 return state, gen
862
861
@@ -917,10 +916,19 b' class cgpacker(object):'
917 size = 0
916 size = 0
918 while tmfnodes:
917 while tmfnodes:
919 dir, nodes = tmfnodes.popitem()
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 if not dir or prunednodes:
921 if not dir or prunednodes:
922 for x in self._packmanifests(dir, prunednodes,
922 lookupfn = makelookupmflinknode(dir, nodes)
923 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 size += len(x)
932 size += len(x)
925 yield x
933 yield x
926 self._verbosenote(_('%8.i (manifests)\n') % size)
934 self._verbosenote(_('%8.i (manifests)\n') % size)
@@ -981,12 +989,18 b' class cgpacker(object):'
981
989
982 filenodes = self._prune(filerevlog, linkrevnodes, commonrevs)
990 filenodes = self._prune(filerevlog, linkrevnodes, commonrevs)
983 if filenodes:
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 progress.update(i + 1, item=fname)
999 progress.update(i + 1, item=fname)
985 h = _fileheader(fname)
1000 h = _fileheader(fname)
986 size = len(h)
1001 size = len(h)
987 yield h
1002 yield h
988 for chunk in self.group(filenodes, filerevlog, False,
1003 for chunk in self.group(revs, filerevlog, False, lookupfilelog):
989 lookupfilelog):
990 size += len(chunk)
1004 size += len(chunk)
991 yield chunk
1005 yield chunk
992 self._verbosenote(_('%8.i %s\n') % (size, fname))
1006 self._verbosenote(_('%8.i %s\n') % (size, fname))
General Comments 0
You need to be logged in to leave comments. Login now