mercurial/changegroup.py
changeset 38907 ad4c4cc9a5ac
parent 38906 0548f696795b
child 38908 1469584ad5fe
equal deleted inserted replaced
38906:0548f696795b 38907:ad4c4cc9a5ac
   520     deltachunks = attr.ib()
   520     deltachunks = attr.ib()
   521 
   521 
   522 class cgpacker(object):
   522 class cgpacker(object):
   523     def __init__(self, repo, filematcher, version, allowreorder,
   523     def __init__(self, repo, filematcher, version, allowreorder,
   524                  useprevdelta, builddeltaheader, manifestsend,
   524                  useprevdelta, builddeltaheader, manifestsend,
   525                  sendtreemanifests, bundlecaps=None, shallow=False):
   525                  sendtreemanifests, bundlecaps=None, shallow=False,
       
   526                  ellipsisroots=None):
   526         """Given a source repo, construct a bundler.
   527         """Given a source repo, construct a bundler.
   527 
   528 
   528         filematcher is a matcher that matches on files to include in the
   529         filematcher is a matcher that matches on files to include in the
   529         changegroup. Used to facilitate sparse changegroups.
   530         changegroup. Used to facilitate sparse changegroups.
   530 
   531 
   562         # Set of capabilities we can use to build the bundle.
   563         # Set of capabilities we can use to build the bundle.
   563         if bundlecaps is None:
   564         if bundlecaps is None:
   564             bundlecaps = set()
   565             bundlecaps = set()
   565         self._bundlecaps = bundlecaps
   566         self._bundlecaps = bundlecaps
   566         self._isshallow = shallow
   567         self._isshallow = shallow
       
   568 
       
   569         # Maps ellipsis revs to their roots at the changelog level.
       
   570         self._precomputedellipsis = ellipsisroots
   567 
   571 
   568         # experimental config: bundle.reorder
   572         # experimental config: bundle.reorder
   569         reorder = repo.ui.config('bundle', 'reorder')
   573         reorder = repo.ui.config('bundle', 'reorder')
   570         if reorder == 'auto':
   574         if reorder == 'auto':
   571             self._reorder = allowreorder
   575             self._reorder = allowreorder
   738                 # Only update mfs if x is going to be sent. Otherwise we
   742                 # Only update mfs if x is going to be sent. Otherwise we
   739                 # end up with bogus linkrevs specified for manifests and
   743                 # end up with bogus linkrevs specified for manifests and
   740                 # we skip some manifest nodes that we should otherwise
   744                 # we skip some manifest nodes that we should otherwise
   741                 # have sent.
   745                 # have sent.
   742                 if (x in self._full_nodes
   746                 if (x in self._full_nodes
   743                     or cl.rev(x) in self._precomputed_ellipsis):
   747                     or cl.rev(x) in self._precomputedellipsis):
   744                     n = c[0]
   748                     n = c[0]
   745                     # Record the first changeset introducing this manifest
   749                     # Record the first changeset introducing this manifest
   746                     # version.
   750                     # version.
   747                     mfs.setdefault(n, x)
   751                     mfs.setdefault(n, x)
   748                     # Set this narrow-specific dict so we have the lowest
   752                     # Set this narrow-specific dict so we have the lowest
  1084         if linknode in self._full_nodes:
  1088         if linknode in self._full_nodes:
  1085             return self._revisiondeltanormal(store, rev, prev, linknode)
  1089             return self._revisiondeltanormal(store, rev, prev, linknode)
  1086 
  1090 
  1087         # At this point, a node can either be one we should skip or an
  1091         # At this point, a node can either be one we should skip or an
  1088         # ellipsis. If it's not an ellipsis, bail immediately.
  1092         # ellipsis. If it's not an ellipsis, bail immediately.
  1089         if linkrev not in self._precomputed_ellipsis:
  1093         if linkrev not in self._precomputedellipsis:
  1090             return
  1094             return
  1091 
  1095 
  1092         linkparents = self._precomputed_ellipsis[linkrev]
  1096         linkparents = self._precomputedellipsis[linkrev]
  1093         def local(clrev):
  1097         def local(clrev):
  1094             """Turn a changelog revnum into a local revnum.
  1098             """Turn a changelog revnum into a local revnum.
  1095 
  1099 
  1096             The ellipsis dag is stored as revnums on the changelog,
  1100             The ellipsis dag is stored as revnums on the changelog,
  1097             but when we're producing ellipsis entries for
  1101             but when we're producing ellipsis entries for
  1131                 if p in self._clrevtolocalrev:
  1135                 if p in self._clrevtolocalrev:
  1132                     return self._clrevtolocalrev[p]
  1136                     return self._clrevtolocalrev[p]
  1133                 elif p in self._full_nodes:
  1137                 elif p in self._full_nodes:
  1134                     walk.extend([pp for pp in self._repo.changelog.parentrevs(p)
  1138                     walk.extend([pp for pp in self._repo.changelog.parentrevs(p)
  1135                                     if pp != nullrev])
  1139                                     if pp != nullrev])
  1136                 elif p in self._precomputed_ellipsis:
  1140                 elif p in self._precomputedellipsis:
  1137                     walk.extend([pp for pp in self._precomputed_ellipsis[p]
  1141                     walk.extend([pp for pp in self._precomputedellipsis[p]
  1138                                     if pp != nullrev])
  1142                                     if pp != nullrev])
  1139                 else:
  1143                 else:
  1140                     # In this case, we've got an ellipsis with parents
  1144                     # In this case, we've got an ellipsis with parents
  1141                     # outside the current bundle (likely an
  1145                     # outside the current bundle (likely an
  1142                     # incremental pull). We "know" that we can use the
  1146                     # incremental pull). We "know" that we can use the
  1186             linknode=linknode,
  1190             linknode=linknode,
  1187             flags=flags,
  1191             flags=flags,
  1188             deltachunks=(diffheader, data),
  1192             deltachunks=(diffheader, data),
  1189         )
  1193         )
  1190 
  1194 
  1191 def _makecg1packer(repo, filematcher, bundlecaps, shallow=False):
  1195 def _makecg1packer(repo, filematcher, bundlecaps, shallow=False,
       
  1196                    ellipsisroots=None):
  1192     builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack(
  1197     builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack(
  1193         d.node, d.p1node, d.p2node, d.linknode)
  1198         d.node, d.p1node, d.p2node, d.linknode)
  1194 
  1199 
  1195     return cgpacker(repo, filematcher, b'01',
  1200     return cgpacker(repo, filematcher, b'01',
  1196                     useprevdelta=True,
  1201                     useprevdelta=True,
  1197                     allowreorder=None,
  1202                     allowreorder=None,
  1198                     builddeltaheader=builddeltaheader,
  1203                     builddeltaheader=builddeltaheader,
  1199                     manifestsend=b'',
  1204                     manifestsend=b'',
  1200                     sendtreemanifests=False,
  1205                     sendtreemanifests=False,
  1201                     bundlecaps=bundlecaps,
  1206                     bundlecaps=bundlecaps,
  1202                     shallow=shallow)
  1207                     shallow=shallow,
  1203 
  1208                     ellipsisroots=ellipsisroots)
  1204 def _makecg2packer(repo, filematcher, bundlecaps, shallow=False):
  1209 
       
  1210 def _makecg2packer(repo, filematcher, bundlecaps, shallow=False,
       
  1211                    ellipsisroots=None):
  1205     builddeltaheader = lambda d: _CHANGEGROUPV2_DELTA_HEADER.pack(
  1212     builddeltaheader = lambda d: _CHANGEGROUPV2_DELTA_HEADER.pack(
  1206         d.node, d.p1node, d.p2node, d.basenode, d.linknode)
  1213         d.node, d.p1node, d.p2node, d.basenode, d.linknode)
  1207 
  1214 
  1208     # Since generaldelta is directly supported by cg2, reordering
  1215     # Since generaldelta is directly supported by cg2, reordering
  1209     # generally doesn't help, so we disable it by default (treating
  1216     # generally doesn't help, so we disable it by default (treating
  1213                     allowreorder=False,
  1220                     allowreorder=False,
  1214                     builddeltaheader=builddeltaheader,
  1221                     builddeltaheader=builddeltaheader,
  1215                     manifestsend=b'',
  1222                     manifestsend=b'',
  1216                     sendtreemanifests=False,
  1223                     sendtreemanifests=False,
  1217                     bundlecaps=bundlecaps,
  1224                     bundlecaps=bundlecaps,
  1218                     shallow=shallow)
  1225                     shallow=shallow,
  1219 
  1226                     ellipsisroots=ellipsisroots)
  1220 def _makecg3packer(repo, filematcher, bundlecaps, shallow=False):
  1227 
       
  1228 def _makecg3packer(repo, filematcher, bundlecaps, shallow=False,
       
  1229                    ellipsisroots=None):
  1221     builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack(
  1230     builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack(
  1222         d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags)
  1231         d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags)
  1223 
  1232 
  1224     return cgpacker(repo, filematcher, b'03',
  1233     return cgpacker(repo, filematcher, b'03',
  1225                     useprevdelta=False,
  1234                     useprevdelta=False,
  1226                     allowreorder=False,
  1235                     allowreorder=False,
  1227                     builddeltaheader=builddeltaheader,
  1236                     builddeltaheader=builddeltaheader,
  1228                     manifestsend=closechunk(),
  1237                     manifestsend=closechunk(),
  1229                     sendtreemanifests=True,
  1238                     sendtreemanifests=True,
  1230                     bundlecaps=bundlecaps,
  1239                     bundlecaps=bundlecaps,
  1231                     shallow=shallow)
  1240                     shallow=shallow,
       
  1241                     ellipsisroots=ellipsisroots)
  1232 
  1242 
  1233 _packermap = {'01': (_makecg1packer, cg1unpacker),
  1243 _packermap = {'01': (_makecg1packer, cg1unpacker),
  1234              # cg2 adds support for exchanging generaldelta
  1244              # cg2 adds support for exchanging generaldelta
  1235              '02': (_makecg2packer, cg2unpacker),
  1245              '02': (_makecg2packer, cg2unpacker),
  1236              # cg3 adds support for exchanging revlog flags and treemanifests
  1246              # cg3 adds support for exchanging revlog flags and treemanifests
  1287         versions.discard('01')
  1297         versions.discard('01')
  1288     assert versions
  1298     assert versions
  1289     return min(versions)
  1299     return min(versions)
  1290 
  1300 
  1291 def getbundler(version, repo, bundlecaps=None, filematcher=None,
  1301 def getbundler(version, repo, bundlecaps=None, filematcher=None,
  1292                shallow=False):
  1302                shallow=False, ellipsisroots=None):
  1293     assert version in supportedoutgoingversions(repo)
  1303     assert version in supportedoutgoingversions(repo)
  1294 
  1304 
  1295     if filematcher is None:
  1305     if filematcher is None:
  1296         filematcher = matchmod.alwaysmatcher(repo.root, '')
  1306         filematcher = matchmod.alwaysmatcher(repo.root, '')
  1297 
  1307 
  1303     # filter those out.
  1313     # filter those out.
  1304     filematcher = matchmod.intersectmatchers(repo.narrowmatch(),
  1314     filematcher = matchmod.intersectmatchers(repo.narrowmatch(),
  1305                                              filematcher)
  1315                                              filematcher)
  1306 
  1316 
  1307     fn = _packermap[version][0]
  1317     fn = _packermap[version][0]
  1308     return fn(repo, filematcher, bundlecaps, shallow=shallow)
  1318     return fn(repo, filematcher, bundlecaps, shallow=shallow,
       
  1319               ellipsisroots=ellipsisroots)
  1309 
  1320 
  1310 def getunbundler(version, fh, alg, extras=None):
  1321 def getunbundler(version, fh, alg, extras=None):
  1311     return _packermap[version][1](fh, alg, extras=extras)
  1322     return _packermap[version][1](fh, alg, extras=extras)
  1312 
  1323 
  1313 def _changegroupinfo(repo, nodes, source):
  1324 def _changegroupinfo(repo, nodes, source):
  1399     # relevant_nodes into that area. Then if linknode isn't in the
  1410     # relevant_nodes into that area. Then if linknode isn't in the
  1400     # set, we know we have an ellipsis node and we should defer
  1411     # set, we know we have an ellipsis node and we should defer
  1401     # sending that node's data. We override close() to detect
  1412     # sending that node's data. We override close() to detect
  1402     # pending ellipsis nodes and flush them.
  1413     # pending ellipsis nodes and flush them.
  1403     packer = getbundler(version, repo, filematcher=match,
  1414     packer = getbundler(version, repo, filematcher=match,
  1404                         shallow=depth is not None)
  1415                         shallow=depth is not None,
       
  1416                         ellipsisroots=ellipsisroots)
  1405     # Give the packer the list of nodes which should not be
  1417     # Give the packer the list of nodes which should not be
  1406     # ellipsis nodes. We store this rather than the set of nodes
  1418     # ellipsis nodes. We store this rather than the set of nodes
  1407     # that should be an ellipsis because for very large histories
  1419     # that should be an ellipsis because for very large histories
  1408     # we expect this to be significantly smaller.
  1420     # we expect this to be significantly smaller.
  1409     packer._full_nodes = relevant_nodes
  1421     packer._full_nodes = relevant_nodes
  1410     # Maps ellipsis revs to their roots at the changelog level.
       
  1411     packer._precomputed_ellipsis = ellipsisroots
       
  1412 
  1422 
  1413     return packer.generate(common, visitnodes, False, source)
  1423     return packer.generate(common, visitnodes, False, source)