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 #