comparison mercurial/changegroup.py @ 38899:7a154778fb46

changegroup: consolidate tree manifests sending into cg1packer Previously, we overrode a method to control how manifests were serialized. This method was redefined on cg3packer to send tree manifests. This commit moves the tree manifests sending variation to cg1packer and teaches the cgpacker constructor to control which version to use. After these changes, cg3packer was empty. So it has been removed. Differential Revision: https://phab.mercurial-scm.org/D4081
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 03 Aug 2018 09:44:30 -0700
parents 67f37e8a5490
children 6e999a2d8fe7
comparison
equal deleted inserted replaced
38898:67f37e8a5490 38899:7a154778fb46
519 # Iterable of chunks holding raw delta data. 519 # Iterable of chunks holding raw delta data.
520 deltachunks = attr.ib() 520 deltachunks = attr.ib()
521 521
522 class cg1packer(object): 522 class cg1packer(object):
523 def __init__(self, repo, filematcher, version, builddeltaheader, 523 def __init__(self, repo, filematcher, version, builddeltaheader,
524 manifestsend, 524 manifestsend, sendtreemanifests,
525 bundlecaps=None): 525 bundlecaps=None):
526 """Given a source repo, construct a bundler. 526 """Given a source repo, construct a bundler.
527 527
528 filematcher is a matcher that matches on files to include in the 528 filematcher is a matcher that matches on files to include in the
529 changegroup. Used to facilitate sparse changegroups. 529 changegroup. Used to facilitate sparse changegroups.
530 530
531 builddeltaheader is a callable that constructs the header for a group 531 builddeltaheader is a callable that constructs the header for a group
532 delta. 532 delta.
533 533
534 manifestsend is a chunk to send after manifests have been fully emitted. 534 manifestsend is a chunk to send after manifests have been fully emitted.
535
536 sendtreemanifests indicates whether tree manifests should be emitted.
535 537
536 bundlecaps is optional and can be used to specify the set of 538 bundlecaps is optional and can be used to specify the set of
537 capabilities which can be used to build the bundle. While bundlecaps is 539 capabilities which can be used to build the bundle. While bundlecaps is
538 unused in core Mercurial, extensions rely on this feature to communicate 540 unused in core Mercurial, extensions rely on this feature to communicate
539 capabilities to customize the changegroup packer. 541 capabilities to customize the changegroup packer.
542 self._filematcher = filematcher 544 self._filematcher = filematcher
543 545
544 self.version = version 546 self.version = version
545 self._builddeltaheader = builddeltaheader 547 self._builddeltaheader = builddeltaheader
546 self._manifestsend = manifestsend 548 self._manifestsend = manifestsend
549 self._sendtreemanifests = sendtreemanifests
547 550
548 # Set of capabilities we can use to build the bundle. 551 # Set of capabilities we can use to build the bundle.
549 if bundlecaps is None: 552 if bundlecaps is None:
550 bundlecaps = set() 553 bundlecaps = set()
551 self._bundlecaps = bundlecaps 554 self._bundlecaps = bundlecaps
661 def _packmanifests(self, dir, mfnodes, lookuplinknode): 664 def _packmanifests(self, dir, mfnodes, lookuplinknode):
662 """Pack flat manifests into a changegroup stream.""" 665 """Pack flat manifests into a changegroup stream."""
663 assert not dir 666 assert not dir
664 for chunk in self.group(mfnodes, self._repo.manifestlog._revlog, 667 for chunk in self.group(mfnodes, self._repo.manifestlog._revlog,
665 lookuplinknode, units=_('manifests')): 668 lookuplinknode, units=_('manifests')):
669 yield chunk
670
671 def _packtreemanifests(self, dir, mfnodes, lookuplinknode):
672 """Version of _packmanifests that operates on directory manifests.
673
674 Encodes the directory name in the output so multiple manifests
675 can be sent.
676 """
677 assert self.version == b'03'
678
679 if dir:
680 yield self.fileheader(dir)
681
682 # TODO violates storage abstractions by assuming revlogs.
683 dirlog = self._repo.manifestlog._revlog.dirlog(dir)
684 for chunk in self.group(mfnodes, dirlog, lookuplinknode,
685 units=_('manifests')):
666 yield chunk 686 yield chunk
667 687
668 def generate(self, commonrevs, clnodes, fastpathlinkrev, source): 688 def generate(self, commonrevs, clnodes, fastpathlinkrev, source):
669 '''yield a sequence of changegroup chunks (strings)''' 689 '''yield a sequence of changegroup chunks (strings)'''
670 repo = self._repo 690 repo = self._repo
843 if clrevorder[clnode] < clrevorder[fclnode]: 863 if clrevorder[clnode] < clrevorder[fclnode]:
844 fclnodes[n] = clnode 864 fclnodes[n] = clnode
845 return clnode 865 return clnode
846 return lookupmflinknode 866 return lookupmflinknode
847 867
868 fn = (self._packtreemanifests if self._sendtreemanifests
869 else self._packmanifests)
848 size = 0 870 size = 0
849 while tmfnodes: 871 while tmfnodes:
850 dir, nodes = tmfnodes.popitem() 872 dir, nodes = tmfnodes.popitem()
851 prunednodes = self.prune(dirlog(dir), nodes, commonrevs) 873 prunednodes = self.prune(dirlog(dir), nodes, commonrevs)
852 if not dir or prunednodes: 874 if not dir or prunednodes:
853 for x in self._packmanifests(dir, prunednodes, 875 for x in fn(dir, prunednodes, makelookupmflinknode(dir, nodes)):
854 makelookupmflinknode(dir, nodes)):
855 size += len(x) 876 size += len(x)
856 yield x 877 yield x
857 self._verbosenote(_('%8.i (manifests)\n') % size) 878 self._verbosenote(_('%8.i (manifests)\n') % size)
858 yield self._manifestsend 879 yield self._manifestsend
859 880
1098 deltachunks=(diffheader, data), 1119 deltachunks=(diffheader, data),
1099 ) 1120 )
1100 1121
1101 class cg2packer(cg1packer): 1122 class cg2packer(cg1packer):
1102 def __init__(self, repo, filematcher, version, builddeltaheader, 1123 def __init__(self, repo, filematcher, version, builddeltaheader,
1103 manifestsend, bundlecaps=None): 1124 manifestsend, sendtreemanifests, bundlecaps=None):
1104 super(cg2packer, self).__init__(repo, filematcher, version, 1125 super(cg2packer, self).__init__(repo, filematcher, version,
1105 builddeltaheader, manifestsend, 1126 builddeltaheader, manifestsend,
1127 sendtreemanifests,
1106 bundlecaps=bundlecaps) 1128 bundlecaps=bundlecaps)
1107 1129
1108 if self._reorder is None: 1130 if self._reorder is None:
1109 # Since generaldelta is directly supported by cg2, reordering 1131 # Since generaldelta is directly supported by cg2, reordering
1110 # generally doesn't help, so we disable it by default (treating 1132 # generally doesn't help, so we disable it by default (treating
1148 base = dp 1170 base = dp
1149 if base != nullrev and not store.candelta(base, rev): 1171 if base != nullrev and not store.candelta(base, rev):
1150 base = nullrev 1172 base = nullrev
1151 return base 1173 return base
1152 1174
1153 class cg3packer(cg2packer):
1154 def _packmanifests(self, dir, mfnodes, lookuplinknode):
1155 if dir:
1156 yield self.fileheader(dir)
1157
1158 dirlog = self._repo.manifestlog._revlog.dirlog(dir)
1159 for chunk in self.group(mfnodes, dirlog, lookuplinknode,
1160 units=_('manifests')):
1161 yield chunk
1162
1163 def _makecg1packer(repo, filematcher, bundlecaps): 1175 def _makecg1packer(repo, filematcher, bundlecaps):
1164 builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( 1176 builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack(
1165 d.node, d.p1node, d.p2node, d.linknode) 1177 d.node, d.p1node, d.p2node, d.linknode)
1166 1178
1167 return cg1packer(repo, filematcher, b'01', builddeltaheader, 1179 return cg1packer(repo, filematcher, b'01', builddeltaheader,
1168 manifestsend=b'', 1180 manifestsend=b'', sendtreemanifests=False,
1169 bundlecaps=bundlecaps) 1181 bundlecaps=bundlecaps)
1170 1182
1171 def _makecg2packer(repo, filematcher, bundlecaps): 1183 def _makecg2packer(repo, filematcher, bundlecaps):
1172 builddeltaheader = lambda d: _CHANGEGROUPV2_DELTA_HEADER.pack( 1184 builddeltaheader = lambda d: _CHANGEGROUPV2_DELTA_HEADER.pack(
1173 d.node, d.p1node, d.p2node, d.basenode, d.linknode) 1185 d.node, d.p1node, d.p2node, d.basenode, d.linknode)
1174 1186
1175 return cg2packer(repo, filematcher, b'02', builddeltaheader, 1187 return cg2packer(repo, filematcher, b'02', builddeltaheader,
1176 manifestsend=b'', 1188 manifestsend=b'', sendtreemanifests=False,
1177 bundlecaps=bundlecaps) 1189 bundlecaps=bundlecaps)
1178 1190
1179 def _makecg3packer(repo, filematcher, bundlecaps): 1191 def _makecg3packer(repo, filematcher, bundlecaps):
1180 builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( 1192 builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack(
1181 d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) 1193 d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags)
1182 1194
1183 return cg3packer(repo, filematcher, b'03', builddeltaheader, 1195 return cg2packer(repo, filematcher, b'03', builddeltaheader,
1184 manifestsend=closechunk(), 1196 manifestsend=closechunk(), sendtreemanifests=True,
1185 bundlecaps=bundlecaps) 1197 bundlecaps=bundlecaps)
1186 1198
1187 _packermap = {'01': (_makecg1packer, cg1unpacker), 1199 _packermap = {'01': (_makecg1packer, cg1unpacker),
1188 # cg2 adds support for exchanging generaldelta 1200 # cg2 adds support for exchanging generaldelta
1189 '02': (_makecg2packer, cg2unpacker), 1201 '02': (_makecg2packer, cg2unpacker),