518 flags = attr.ib() |
518 flags = attr.ib() |
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 deltaheader = _CHANGEGROUPV1_DELTA_HEADER |
523 def __init__(self, repo, filematcher, version, builddeltaheader, |
524 |
524 bundlecaps=None): |
525 def __init__(self, repo, filematcher, version, bundlecaps=None): |
|
526 """Given a source repo, construct a bundler. |
525 """Given a source repo, construct a bundler. |
527 |
526 |
528 filematcher is a matcher that matches on files to include in the |
527 filematcher is a matcher that matches on files to include in the |
529 changegroup. Used to facilitate sparse changegroups. |
528 changegroup. Used to facilitate sparse changegroups. |
|
529 |
|
530 builddeltaheader is a callable that constructs the header for a group |
|
531 delta. |
530 |
532 |
531 bundlecaps is optional and can be used to specify the set of |
533 bundlecaps is optional and can be used to specify the set of |
532 capabilities which can be used to build the bundle. While bundlecaps is |
534 capabilities which can be used to build the bundle. While bundlecaps is |
533 unused in core Mercurial, extensions rely on this feature to communicate |
535 unused in core Mercurial, extensions rely on this feature to communicate |
534 capabilities to customize the changegroup packer. |
536 capabilities to customize the changegroup packer. |
535 """ |
537 """ |
536 assert filematcher |
538 assert filematcher |
537 self._filematcher = filematcher |
539 self._filematcher = filematcher |
538 |
540 |
539 self.version = version |
541 self.version = version |
|
542 self._builddeltaheader = builddeltaheader |
540 |
543 |
541 # Set of capabilities we can use to build the bundle. |
544 # Set of capabilities we can use to build the bundle. |
542 if bundlecaps is None: |
545 if bundlecaps is None: |
543 bundlecaps = set() |
546 bundlecaps = set() |
544 self._bundlecaps = bundlecaps |
547 self._bundlecaps = bundlecaps |
931 |
934 |
932 delta = fn(store, rev, prev, linknode) |
935 delta = fn(store, rev, prev, linknode) |
933 if not delta: |
936 if not delta: |
934 return |
937 return |
935 |
938 |
936 meta = self.builddeltaheader(delta.node, delta.p1node, delta.p2node, |
939 meta = self._builddeltaheader(delta) |
937 delta.basenode, delta.linknode, |
|
938 delta.flags) |
|
939 l = len(meta) + sum(len(x) for x in delta.deltachunks) |
940 l = len(meta) + sum(len(x) for x in delta.deltachunks) |
940 |
941 |
941 yield chunkheader(l) |
942 yield chunkheader(l) |
942 yield meta |
943 yield meta |
943 for x in delta.deltachunks: |
944 for x in delta.deltachunks: |
1094 linknode=linknode, |
1095 linknode=linknode, |
1095 flags=flags, |
1096 flags=flags, |
1096 deltachunks=(diffheader, data), |
1097 deltachunks=(diffheader, data), |
1097 ) |
1098 ) |
1098 |
1099 |
1099 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags): |
|
1100 # do nothing with basenode, it is implicitly the previous one in HG10 |
|
1101 # do nothing with flags, it is implicitly 0 for cg1 and cg2 |
|
1102 return self.deltaheader.pack(node, p1n, p2n, linknode) |
|
1103 |
|
1104 class cg2packer(cg1packer): |
1100 class cg2packer(cg1packer): |
1105 deltaheader = _CHANGEGROUPV2_DELTA_HEADER |
1101 def __init__(self, repo, filematcher, version, builddeltaheader, |
1106 |
1102 bundlecaps=None): |
1107 def __init__(self, repo, filematcher, version, bundlecaps=None): |
|
1108 super(cg2packer, self).__init__(repo, filematcher, version, |
1103 super(cg2packer, self).__init__(repo, filematcher, version, |
|
1104 builddeltaheader, |
1109 bundlecaps=bundlecaps) |
1105 bundlecaps=bundlecaps) |
1110 |
1106 |
1111 if self._reorder is None: |
1107 if self._reorder is None: |
1112 # Since generaldelta is directly supported by cg2, reordering |
1108 # Since generaldelta is directly supported by cg2, reordering |
1113 # generally doesn't help, so we disable it by default (treating |
1109 # generally doesn't help, so we disable it by default (treating |
1151 base = dp |
1147 base = dp |
1152 if base != nullrev and not store.candelta(base, rev): |
1148 if base != nullrev and not store.candelta(base, rev): |
1153 base = nullrev |
1149 base = nullrev |
1154 return base |
1150 return base |
1155 |
1151 |
1156 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags): |
|
1157 # Do nothing with flags, it is implicitly 0 in cg1 and cg2 |
|
1158 return self.deltaheader.pack(node, p1n, p2n, basenode, linknode) |
|
1159 |
|
1160 class cg3packer(cg2packer): |
1152 class cg3packer(cg2packer): |
1161 deltaheader = _CHANGEGROUPV3_DELTA_HEADER |
|
1162 |
|
1163 def _packmanifests(self, dir, mfnodes, lookuplinknode): |
1153 def _packmanifests(self, dir, mfnodes, lookuplinknode): |
1164 if dir: |
1154 if dir: |
1165 yield self.fileheader(dir) |
1155 yield self.fileheader(dir) |
1166 |
1156 |
1167 dirlog = self._repo.manifestlog._revlog.dirlog(dir) |
1157 dirlog = self._repo.manifestlog._revlog.dirlog(dir) |
1170 yield chunk |
1160 yield chunk |
1171 |
1161 |
1172 def _manifestsdone(self): |
1162 def _manifestsdone(self): |
1173 return self.close() |
1163 return self.close() |
1174 |
1164 |
1175 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags): |
|
1176 return self.deltaheader.pack(node, p1n, p2n, basenode, linknode, flags) |
|
1177 |
|
1178 def _makecg1packer(repo, filematcher, bundlecaps): |
1165 def _makecg1packer(repo, filematcher, bundlecaps): |
1179 return cg1packer(repo, filematcher, b'01', bundlecaps=bundlecaps) |
1166 builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( |
|
1167 d.node, d.p1node, d.p2node, d.linknode) |
|
1168 |
|
1169 return cg1packer(repo, filematcher, b'01', builddeltaheader, |
|
1170 bundlecaps=bundlecaps) |
1180 |
1171 |
1181 def _makecg2packer(repo, filematcher, bundlecaps): |
1172 def _makecg2packer(repo, filematcher, bundlecaps): |
1182 return cg2packer(repo, filematcher, b'02', bundlecaps=bundlecaps) |
1173 builddeltaheader = lambda d: _CHANGEGROUPV2_DELTA_HEADER.pack( |
|
1174 d.node, d.p1node, d.p2node, d.basenode, d.linknode) |
|
1175 |
|
1176 return cg2packer(repo, filematcher, b'02', builddeltaheader, |
|
1177 bundlecaps=bundlecaps) |
1183 |
1178 |
1184 def _makecg3packer(repo, filematcher, bundlecaps): |
1179 def _makecg3packer(repo, filematcher, bundlecaps): |
1185 return cg3packer(repo, filematcher, b'03', bundlecaps=bundlecaps) |
1180 builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( |
|
1181 d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) |
|
1182 |
|
1183 return cg3packer(repo, filematcher, b'03', builddeltaheader, |
|
1184 bundlecaps=bundlecaps) |
1186 |
1185 |
1187 _packermap = {'01': (_makecg1packer, cg1unpacker), |
1186 _packermap = {'01': (_makecg1packer, cg1unpacker), |
1188 # cg2 adds support for exchanging generaldelta |
1187 # cg2 adds support for exchanging generaldelta |
1189 '02': (_makecg2packer, cg2unpacker), |
1188 '02': (_makecg2packer, cg2unpacker), |
1190 # cg3 adds support for exchanging revlog flags and treemanifests |
1189 # cg3 adds support for exchanging revlog flags and treemanifests |