Mercurial > hg
comparison mercurial/changegroup.py @ 38997:812eec3f89cb
changegroup: remove _clnodetorev
cgpacker._clnodetorev is a glorified cache/index of changelog
nodes to revision numbers.
I'm not sure why it exists. Maybe performance? But its presence
is making refactoring of this code more complicated than it needs
to be.
This commit removes the cache and replaces it with direct lookups
against the changelog.
If this cache was for performance reasons, we should be able to
restore it easily enough... after the changegroup refactor is
complete.
Differential Revision: https://phab.mercurial-scm.org/D4189
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 07 Aug 2018 10:49:41 -0700 |
parents | 5baafb8fe253 |
children | 40374b4a780f |
comparison
equal
deleted
inserted
replaced
38996:5baafb8fe253 | 38997:812eec3f89cb |
---|---|
531 dag = dagutil.revlogdag(store) | 531 dag = dagutil.revlogdag(store) |
532 return dag.linearize(set(store.rev(n) for n in nodes)) | 532 return dag.linearize(set(store.rev(n) for n in nodes)) |
533 else: | 533 else: |
534 return sorted([store.rev(n) for n in nodes]) | 534 return sorted([store.rev(n) for n in nodes]) |
535 | 535 |
536 def _sortnodesellipsis(store, nodes, clnodetorev, lookup): | 536 def _sortnodesellipsis(store, nodes, cl, lookup): |
537 """Sort nodes for changegroup generation and turn into revnums.""" | 537 """Sort nodes for changegroup generation and turn into revnums.""" |
538 # Ellipses serving mode. | 538 # Ellipses serving mode. |
539 # | 539 # |
540 # In a perfect world, we'd generate better ellipsis-ified graphs | 540 # In a perfect world, we'd generate better ellipsis-ified graphs |
541 # for non-changelog revlogs. In practice, we haven't started doing | 541 # for non-changelog revlogs. In practice, we haven't started doing |
549 # The one invariant we *know* holds is that the new (potentially | 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 | 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 | 551 # order that they're introduced in dramatis personae by the |
552 # changelog, so what we do is we sort the non-changelog histories | 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. | 553 # by the order in which they are used by the changelog. |
554 key = lambda n: clnodetorev[lookup(n)] | 554 key = lambda n: cl.rev(lookup(n)) |
555 return [store.rev(n) for n in sorted(nodes, key=key)] | 555 return [store.rev(n) for n in sorted(nodes, key=key)] |
556 | 556 |
557 def _revisiondeltanormal(store, rev, prev, linknode, deltaparentfn): | 557 def _revisiondeltanormal(store, rev, prev, linknode, deltaparentfn): |
558 """Construct a revision delta for non-ellipses changegroup generation.""" | 558 """Construct a revision delta for non-ellipses changegroup generation.""" |
559 node = store.node(rev) | 559 node = store.node(rev) |
661 # Maps CL revs to per-revlog revisions. Cleared in close() at | 661 # Maps CL revs to per-revlog revisions. Cleared in close() at |
662 # the end of each group. | 662 # the end of each group. |
663 self._clrevtolocalrev = {} | 663 self._clrevtolocalrev = {} |
664 self._nextclrevtolocalrev = {} | 664 self._nextclrevtolocalrev = {} |
665 | 665 |
666 # Maps changelog nodes to changelog revs. Filled in once | |
667 # during changelog stage and then left unmodified. | |
668 self._clnodetorev = {} | |
669 | |
670 def _close(self): | 666 def _close(self): |
671 # Ellipses serving mode. | 667 # Ellipses serving mode. |
672 self._clrevtolocalrev.clear() | 668 self._clrevtolocalrev.clear() |
673 if self._nextclrevtolocalrev is not None: | 669 if self._nextclrevtolocalrev is not None: |
674 self._clrevtolocalrev = self._nextclrevtolocalrev | 670 self._clrevtolocalrev = self._nextclrevtolocalrev |
692 """ | 688 """ |
693 # if we don't have any revisions touched by these changesets, bail | 689 # if we don't have any revisions touched by these changesets, bail |
694 if len(revs) == 0: | 690 if len(revs) == 0: |
695 yield self._close() | 691 yield self._close() |
696 return | 692 return |
693 | |
694 cl = self._repo.changelog | |
697 | 695 |
698 # add the parent of the first rev | 696 # add the parent of the first rev |
699 p = store.parentrevs(revs[0])[0] | 697 p = store.parentrevs(revs[0])[0] |
700 revs.insert(0, p) | 698 revs.insert(0, p) |
701 | 699 |
709 progress.update(r + 1) | 707 progress.update(r + 1) |
710 prev, curr = revs[r], revs[r + 1] | 708 prev, curr = revs[r], revs[r + 1] |
711 linknode = lookup(store.node(curr)) | 709 linknode = lookup(store.node(curr)) |
712 | 710 |
713 if self._ellipses: | 711 if self._ellipses: |
714 linkrev = self._clnodetorev[linknode] | 712 linkrev = cl.rev(linknode) |
715 self._clrevtolocalrev[linkrev] = curr | 713 self._clrevtolocalrev[linkrev] = curr |
716 | 714 |
717 # This is a node to send in full, because the changeset it | 715 # This is a node to send in full, because the changeset it |
718 # corresponds to was a full changeset. | 716 # corresponds to was a full changeset. |
719 if linknode in self._fullclnodes: | 717 if linknode in self._fullclnodes: |
862 def lookupcl(x): | 860 def lookupcl(x): |
863 c = cl.read(x) | 861 c = cl.read(x) |
864 clrevorder[x] = len(clrevorder) | 862 clrevorder[x] = len(clrevorder) |
865 | 863 |
866 if self._ellipses: | 864 if self._ellipses: |
867 self._clnodetorev[x] = cl.rev(x) | |
868 | |
869 # Only update mfs if x is going to be sent. Otherwise we | 865 # Only update mfs if x is going to be sent. Otherwise we |
870 # end up with bogus linkrevs specified for manifests and | 866 # end up with bogus linkrevs specified for manifests and |
871 # we skip some manifest nodes that we should otherwise | 867 # we skip some manifest nodes that we should otherwise |
872 # have sent. | 868 # have sent. |
873 if (x in self._fullclnodes | 869 if (x in self._fullclnodes |
919 | 915 |
920 `source` is unused here, but is used by extensions like remotefilelog to | 916 `source` is unused here, but is used by extensions like remotefilelog to |
921 change what is sent based in pulls vs pushes, etc. | 917 change what is sent based in pulls vs pushes, etc. |
922 """ | 918 """ |
923 repo = self._repo | 919 repo = self._repo |
920 cl = repo.changelog | |
924 mfl = repo.manifestlog | 921 mfl = repo.manifestlog |
925 dirlog = mfl._revlog.dirlog | 922 dirlog = mfl._revlog.dirlog |
926 tmfnodes = {'': mfs} | 923 tmfnodes = {'': mfs} |
927 | 924 |
928 # Callback for the manifest, used to collect linkrevs for filelog | 925 # Callback for the manifest, used to collect linkrevs for filelog |
974 prunednodes = self._prune(store, nodes, commonrevs) | 971 prunednodes = self._prune(store, nodes, commonrevs) |
975 if not dir or prunednodes: | 972 if not dir or prunednodes: |
976 lookupfn = makelookupmflinknode(dir, nodes) | 973 lookupfn = makelookupmflinknode(dir, nodes) |
977 | 974 |
978 if self._ellipses: | 975 if self._ellipses: |
979 revs = _sortnodesellipsis(store, prunednodes, | 976 revs = _sortnodesellipsis(store, prunednodes, cl, |
980 self._clnodetorev, lookupfn) | 977 lookupfn) |
981 else: | 978 else: |
982 revs = _sortnodesnormal(store, prunednodes, | 979 revs = _sortnodesnormal(store, prunednodes, |
983 self._reorder) | 980 self._reorder) |
984 | 981 |
985 for x in self._packmanifests(dir, store, revs, lookupfn): | 982 for x in self._packmanifests(dir, store, revs, lookupfn): |
1023 | 1020 |
1024 return self._generatefiles(changedfiles, linknodes, commonrevs, source) | 1021 return self._generatefiles(changedfiles, linknodes, commonrevs, source) |
1025 | 1022 |
1026 def _generatefiles(self, changedfiles, linknodes, commonrevs, source): | 1023 def _generatefiles(self, changedfiles, linknodes, commonrevs, source): |
1027 repo = self._repo | 1024 repo = self._repo |
1025 cl = repo.changelog | |
1028 progress = repo.ui.makeprogress(_('bundling'), unit=_('files'), | 1026 progress = repo.ui.makeprogress(_('bundling'), unit=_('files'), |
1029 total=len(changedfiles)) | 1027 total=len(changedfiles)) |
1030 for i, fname in enumerate(sorted(changedfiles)): | 1028 for i, fname in enumerate(sorted(changedfiles)): |
1031 filerevlog = repo.file(fname) | 1029 filerevlog = repo.file(fname) |
1032 if not filerevlog: | 1030 if not filerevlog: |
1041 | 1039 |
1042 filenodes = self._prune(filerevlog, linkrevnodes, commonrevs) | 1040 filenodes = self._prune(filerevlog, linkrevnodes, commonrevs) |
1043 if filenodes: | 1041 if filenodes: |
1044 if self._ellipses: | 1042 if self._ellipses: |
1045 revs = _sortnodesellipsis(filerevlog, filenodes, | 1043 revs = _sortnodesellipsis(filerevlog, filenodes, |
1046 self._clnodetorev, lookupfilelog) | 1044 cl, lookupfilelog) |
1047 else: | 1045 else: |
1048 revs = _sortnodesnormal(filerevlog, filenodes, | 1046 revs = _sortnodesnormal(filerevlog, filenodes, |
1049 self._reorder) | 1047 self._reorder) |
1050 | 1048 |
1051 progress.update(i + 1, item=fname) | 1049 progress.update(i + 1, item=fname) |
1072 """ | 1070 """ |
1073 if clrev == nullrev: | 1071 if clrev == nullrev: |
1074 return nullrev | 1072 return nullrev |
1075 | 1073 |
1076 if ischangelog: | 1074 if ischangelog: |
1077 # If we're doing the changelog, it's possible that we | |
1078 # have a parent that is already on the client, and we | |
1079 # need to store some extra mapping information so that | |
1080 # our contained ellipsis nodes will be able to resolve | |
1081 # their parents. | |
1082 if clrev not in self._clrevtolocalrev: | |
1083 clnode = store.node(clrev) | |
1084 self._clnodetorev[clnode] = clrev | |
1085 return clrev | 1075 return clrev |
1086 | 1076 |
1087 # Walk the ellipsis-ized changelog breadth-first looking for a | 1077 # Walk the ellipsis-ized changelog breadth-first looking for a |
1088 # change that has been linked from the current revlog. | 1078 # change that has been linked from the current revlog. |
1089 # | 1079 # |