comparison mercurial/changegroup.py @ 38980:4a202bccafcf

changegroup: factor changelogdone into an argument The variable was basically tracking whether the current operation is being performed against the changelog or something else. So let's just pass such a flag to everything that needs to access it. I'm still not a huge fan of building changelog awareness into low-level functions like revision delta generation. But passing an argument is strictly better than state on the packer instance. Differential Revision: https://phab.mercurial-scm.org/D4137
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 06 Aug 2018 09:26:02 -0700
parents 6d726d1b08cb
children 227ebd88ce5e
comparison
equal deleted inserted replaced
38979:6d726d1b08cb 38980:4a202bccafcf
586 if self._repo.ui.verbose and not self._repo.ui.debugflag: 586 if self._repo.ui.verbose and not self._repo.ui.debugflag:
587 self._verbosenote = self._repo.ui.note 587 self._verbosenote = self._repo.ui.note
588 else: 588 else:
589 self._verbosenote = lambda s: None 589 self._verbosenote = lambda s: None
590 590
591 # TODO the functionality keyed off of this should probably be
592 # controlled via arguments to group() that influence behavior.
593 self._changelogdone = False
594
595 # Maps CL revs to per-revlog revisions. Cleared in close() at 591 # Maps CL revs to per-revlog revisions. Cleared in close() at
596 # the end of each group. 592 # the end of each group.
597 self._clrevtolocalrev = {} 593 self._clrevtolocalrev = {}
598 self._nextclrevtolocalrev = {} 594 self._nextclrevtolocalrev = {}
599 595
612 608
613 def _fileheader(self, fname): 609 def _fileheader(self, fname):
614 return chunkheader(len(fname)) + fname 610 return chunkheader(len(fname)) + fname
615 611
616 # Extracted both for clarity and for overriding in extensions. 612 # Extracted both for clarity and for overriding in extensions.
617 def _sortgroup(self, store, nodelist, lookup): 613 def _sortgroup(self, store, ischangelog, nodelist, lookup):
618 """Sort nodes for change group and turn them into revnums.""" 614 """Sort nodes for change group and turn them into revnums."""
619 # Ellipses serving mode. 615 # Ellipses serving mode.
620 # 616 #
621 # In a perfect world, we'd generate better ellipsis-ified graphs 617 # In a perfect world, we'd generate better ellipsis-ified graphs
622 # for non-changelog revlogs. In practice, we haven't started doing 618 # for non-changelog revlogs. In practice, we haven't started doing
630 # The one invariant we *know* holds is that the new (potentially 626 # The one invariant we *know* holds is that the new (potentially
631 # bogus) DAG shape will be valid if we order the nodes in the 627 # bogus) DAG shape will be valid if we order the nodes in the
632 # order that they're introduced in dramatis personae by the 628 # order that they're introduced in dramatis personae by the
633 # changelog, so what we do is we sort the non-changelog histories 629 # changelog, so what we do is we sort the non-changelog histories
634 # by the order in which they are used by the changelog. 630 # by the order in which they are used by the changelog.
635 if self._ellipses and self._changelogdone: 631 if self._ellipses and not ischangelog:
636 key = lambda n: self._clnodetorev[lookup(n)] 632 key = lambda n: self._clnodetorev[lookup(n)]
637 return [store.rev(n) for n in sorted(nodelist, key=key)] 633 return [store.rev(n) for n in sorted(nodelist, key=key)]
638 634
639 # for generaldelta revlogs, we linearize the revs; this will both be 635 # for generaldelta revlogs, we linearize the revs; this will both be
640 # much quicker and generate a much smaller bundle 636 # much quicker and generate a much smaller bundle
642 dag = dagutil.revlogdag(store) 638 dag = dagutil.revlogdag(store)
643 return dag.linearize(set(store.rev(n) for n in nodelist)) 639 return dag.linearize(set(store.rev(n) for n in nodelist))
644 else: 640 else:
645 return sorted([store.rev(n) for n in nodelist]) 641 return sorted([store.rev(n) for n in nodelist])
646 642
647 def group(self, nodelist, store, lookup, units=None): 643 def group(self, nodelist, store, ischangelog, lookup, units=None):
648 """Calculate a delta group, yielding a sequence of changegroup chunks 644 """Calculate a delta group, yielding a sequence of changegroup chunks
649 (strings). 645 (strings).
650 646
651 Given a list of changeset revs, return a set of deltas and 647 Given a list of changeset revs, return a set of deltas and
652 metadata corresponding to nodes. The first delta is 648 metadata corresponding to nodes. The first delta is
661 # if we don't have any revisions touched by these changesets, bail 657 # if we don't have any revisions touched by these changesets, bail
662 if len(nodelist) == 0: 658 if len(nodelist) == 0:
663 yield self._close() 659 yield self._close()
664 return 660 return
665 661
666 revs = self._sortgroup(store, nodelist, lookup) 662 revs = self._sortgroup(store, ischangelog, nodelist, lookup)
667 663
668 # add the parent of the first rev 664 # add the parent of the first rev
669 p = store.parentrevs(revs[0])[0] 665 p = store.parentrevs(revs[0])[0]
670 revs.insert(0, p) 666 revs.insert(0, p)
671 667
677 for r in pycompat.xrange(len(revs) - 1): 673 for r in pycompat.xrange(len(revs) - 1):
678 if progress: 674 if progress:
679 progress.update(r + 1) 675 progress.update(r + 1)
680 prev, curr = revs[r], revs[r + 1] 676 prev, curr = revs[r], revs[r + 1]
681 linknode = lookup(store.node(curr)) 677 linknode = lookup(store.node(curr))
682 for c in self._revchunk(store, curr, prev, linknode): 678 for c in self._revchunk(store, ischangelog, curr, prev, linknode):
683 yield c 679 yield c
684 680
685 if progress: 681 if progress:
686 progress.complete() 682 progress.complete()
687 yield self._close() 683 yield self._close()
707 assert self.version == b'03' 703 assert self.version == b'03'
708 yield self._fileheader(dir) 704 yield self._fileheader(dir)
709 705
710 # TODO violates storage abstractions by assuming revlogs. 706 # TODO violates storage abstractions by assuming revlogs.
711 dirlog = self._repo.manifestlog._revlog.dirlog(dir) 707 dirlog = self._repo.manifestlog._revlog.dirlog(dir)
712 for chunk in self.group(mfnodes, dirlog, lookuplinknode, 708 for chunk in self.group(mfnodes, dirlog, False, lookuplinknode,
713 units=_('manifests')): 709 units=_('manifests')):
714 yield chunk 710 yield chunk
715 711
716 def generate(self, commonrevs, clnodes, fastpathlinkrev, source): 712 def generate(self, commonrevs, clnodes, fastpathlinkrev, source):
717 """Yield a sequence of changegroup byte chunks.""" 713 """Yield a sequence of changegroup byte chunks."""
726 for chunk in chunks: 722 for chunk in chunks:
727 size += len(chunk) 723 size += len(chunk)
728 yield chunk 724 yield chunk
729 725
730 self._verbosenote(_('%8.i (changelog)\n') % size) 726 self._verbosenote(_('%8.i (changelog)\n') % size)
731
732 self._changelogdone = True
733 727
734 clrevorder = clstate['clrevorder'] 728 clrevorder = clstate['clrevorder']
735 mfs = clstate['mfs'] 729 mfs = clstate['mfs']
736 changedfiles = clstate['changedfiles'] 730 changedfiles = clstate['changedfiles']
737 731
859 'clrevorder': clrevorder, 853 'clrevorder': clrevorder,
860 'mfs': mfs, 854 'mfs': mfs,
861 'changedfiles': changedfiles, 855 'changedfiles': changedfiles,
862 } 856 }
863 857
864 gen = self.group(nodes, cl, lookupcl, units=_('changesets')) 858 gen = self.group(nodes, cl, True, lookupcl, units=_('changesets'))
865 859
866 return state, gen 860 return state, gen
867 861
868 def generatemanifests(self, commonrevs, clrevorder, fastpathlinkrev, mfs, 862 def generatemanifests(self, commonrevs, clrevorder, fastpathlinkrev, mfs,
869 fnodes, source): 863 fnodes, source):
988 if filenodes: 982 if filenodes:
989 progress.update(i + 1, item=fname) 983 progress.update(i + 1, item=fname)
990 h = self._fileheader(fname) 984 h = self._fileheader(fname)
991 size = len(h) 985 size = len(h)
992 yield h 986 yield h
993 for chunk in self.group(filenodes, filerevlog, lookupfilelog): 987 for chunk in self.group(filenodes, filerevlog, False,
988 lookupfilelog):
994 size += len(chunk) 989 size += len(chunk)
995 yield chunk 990 yield chunk
996 self._verbosenote(_('%8.i %s\n') % (size, fname)) 991 self._verbosenote(_('%8.i %s\n') % (size, fname))
997 progress.complete() 992 progress.complete()
998 993
999 def _revchunk(self, store, rev, prev, linknode): 994 def _revchunk(self, store, ischangelog, rev, prev, linknode):
1000 if self._ellipses: 995 if self._ellipses:
1001 fn = self._revisiondeltanarrow 996 fn = self._revisiondeltanarrow
1002 else: 997 else:
1003 fn = self._revisiondeltanormal 998 fn = self._revisiondeltanormal
1004 999
1005 delta = fn(store, rev, prev, linknode) 1000 delta = fn(store, ischangelog, rev, prev, linknode)
1006 if not delta: 1001 if not delta:
1007 return 1002 return
1008 1003
1009 meta = self._builddeltaheader(delta) 1004 meta = self._builddeltaheader(delta)
1010 l = len(meta) + sum(len(x) for x in delta.deltachunks) 1005 l = len(meta) + sum(len(x) for x in delta.deltachunks)
1012 yield chunkheader(l) 1007 yield chunkheader(l)
1013 yield meta 1008 yield meta
1014 for x in delta.deltachunks: 1009 for x in delta.deltachunks:
1015 yield x 1010 yield x
1016 1011
1017 def _revisiondeltanormal(self, store, rev, prev, linknode): 1012 def _revisiondeltanormal(self, store, ischangelog, rev, prev, linknode):
1018 node = store.node(rev) 1013 node = store.node(rev)
1019 p1, p2 = store.parentrevs(rev) 1014 p1, p2 = store.parentrevs(rev)
1020 base = self._deltaparentfn(store, rev, p1, p2, prev) 1015 base = self._deltaparentfn(store, rev, p1, p2, prev)
1021 1016
1022 prefix = '' 1017 prefix = ''
1045 linknode=linknode, 1040 linknode=linknode,
1046 flags=store.flags(rev), 1041 flags=store.flags(rev),
1047 deltachunks=(prefix, delta), 1042 deltachunks=(prefix, delta),
1048 ) 1043 )
1049 1044
1050 def _revisiondeltanarrow(self, store, rev, prev, linknode): 1045 def _revisiondeltanarrow(self, store, ischangelog, rev, prev, linknode):
1051 # build up some mapping information that's useful later. See 1046 # build up some mapping information that's useful later. See
1052 # the local() nested function below. 1047 # the local() nested function below.
1053 if not self._changelogdone: 1048 if ischangelog:
1054 self._clnodetorev[linknode] = rev 1049 self._clnodetorev[linknode] = rev
1055 linkrev = rev 1050 linkrev = rev
1056 self._clrevtolocalrev[linkrev] = rev 1051 self._clrevtolocalrev[linkrev] = rev
1057 else: 1052 else:
1058 linkrev = self._clnodetorev[linknode] 1053 linkrev = self._clnodetorev[linknode]
1059 self._clrevtolocalrev[linkrev] = rev 1054 self._clrevtolocalrev[linkrev] = rev
1060 1055
1061 # This is a node to send in full, because the changeset it 1056 # This is a node to send in full, because the changeset it
1062 # corresponds to was a full changeset. 1057 # corresponds to was a full changeset.
1063 if linknode in self._fullnodes: 1058 if linknode in self._fullnodes:
1064 return self._revisiondeltanormal(store, rev, prev, linknode) 1059 return self._revisiondeltanormal(store, ischangelog, rev, prev,
1060 linknode)
1065 1061
1066 # At this point, a node can either be one we should skip or an 1062 # At this point, a node can either be one we should skip or an
1067 # ellipsis. If it's not an ellipsis, bail immediately. 1063 # ellipsis. If it's not an ellipsis, bail immediately.
1068 if linkrev not in self._precomputedellipsis: 1064 if linkrev not in self._precomputedellipsis:
1069 return 1065 return
1080 mappings as needed. 1076 mappings as needed.
1081 """ 1077 """
1082 if clrev == nullrev: 1078 if clrev == nullrev:
1083 return nullrev 1079 return nullrev
1084 1080
1085 if not self._changelogdone: 1081 if ischangelog:
1086 # If we're doing the changelog, it's possible that we 1082 # If we're doing the changelog, it's possible that we
1087 # have a parent that is already on the client, and we 1083 # have a parent that is already on the client, and we
1088 # need to store some extra mapping information so that 1084 # need to store some extra mapping information so that
1089 # our contained ellipsis nodes will be able to resolve 1085 # our contained ellipsis nodes will be able to resolve
1090 # their parents. 1086 # their parents.