Mercurial > public > mercurial-scm > hg
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. |