mercurial/exchange.py
changeset 24686 e0e28e910fa3
parent 24650 b83a8f512a80
child 24697 52ff737c63d2
equal deleted inserted replaced
24685:b3d78d82d84c 24686:e0e28e910fa3
    47         remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
    47         remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
    48         version = obsolete.commonversion(remoteversions)
    48         version = obsolete.commonversion(remoteversions)
    49         if version is None:
    49         if version is None:
    50             raise ValueError('bundler do not support common obsmarker format')
    50             raise ValueError('bundler do not support common obsmarker format')
    51         stream = obsolete.encodemarkers(markers, True, version=version)
    51         stream = obsolete.encodemarkers(markers, True, version=version)
    52         return bundler.newpart('b2x:obsmarkers', data=stream)
    52         return bundler.newpart('obsmarkers', data=stream)
    53     return None
    53     return None
    54 
    54 
    55 def _canusebundle2(op):
    55 def _canusebundle2(op):
    56     """return true if a pull/push can use bundle2
    56     """return true if a pull/push can use bundle2
    57 
    57 
    58     Feel free to nuke this function when we drop the experimental option"""
    58     Feel free to nuke this function when we drop the experimental option"""
    59     return (op.repo.ui.configbool('experimental', 'bundle2-exp', False)
    59     return (op.repo.ui.configbool('experimental', 'bundle2-exp', False)
    60             and op.remote.capable('bundle2-exp'))
    60             and op.remote.capable('bundle2'))
    61 
    61 
    62 
    62 
    63 class pushoperation(object):
    63 class pushoperation(object):
    64     """A object that represent a single push operation
    64     """A object that represent a single push operation
    65 
    65 
   457         return
   457         return
   458     pushop.repo.prepushoutgoinghooks(pushop.repo,
   458     pushop.repo.prepushoutgoinghooks(pushop.repo,
   459                                      pushop.remote,
   459                                      pushop.remote,
   460                                      pushop.outgoing)
   460                                      pushop.outgoing)
   461     if not pushop.force:
   461     if not pushop.force:
   462         bundler.newpart('b2x:check:heads', data=iter(pushop.remoteheads))
   462         bundler.newpart('check:heads', data=iter(pushop.remoteheads))
   463     b2caps = bundle2.bundle2caps(pushop.remote)
   463     b2caps = bundle2.bundle2caps(pushop.remote)
   464     version = None
   464     version = None
   465     cgversions = b2caps.get('b2x:changegroup')
   465     cgversions = b2caps.get('changegroup')
   466     if not cgversions:  # 3.1 and 3.2 ship with an empty value
   466     if not cgversions:  # 3.1 and 3.2 ship with an empty value
   467         cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
   467         cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
   468                                                 pushop.outgoing)
   468                                                 pushop.outgoing)
   469     else:
   469     else:
   470         cgversions = [v for v in cgversions if v in changegroup.packermap]
   470         cgversions = [v for v in cgversions if v in changegroup.packermap]
   472             raise ValueError(_('no common changegroup version'))
   472             raise ValueError(_('no common changegroup version'))
   473         version = max(cgversions)
   473         version = max(cgversions)
   474         cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
   474         cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
   475                                                 pushop.outgoing,
   475                                                 pushop.outgoing,
   476                                                 version=version)
   476                                                 version=version)
   477     cgpart = bundler.newpart('b2x:changegroup', data=cg)
   477     cgpart = bundler.newpart('changegroup', data=cg)
   478     if version is not None:
   478     if version is not None:
   479         cgpart.addparam('version', version)
   479         cgpart.addparam('version', version)
   480     def handlereply(op):
   480     def handlereply(op):
   481         """extract addchangegroup returns from server reply"""
   481         """extract addchangegroup returns from server reply"""
   482         cgreplies = op.records.getreplies(cgpart.id)
   482         cgreplies = op.records.getreplies(cgpart.id)
   488 def _pushb2phases(pushop, bundler):
   488 def _pushb2phases(pushop, bundler):
   489     """handle phase push through bundle2"""
   489     """handle phase push through bundle2"""
   490     if 'phases' in pushop.stepsdone:
   490     if 'phases' in pushop.stepsdone:
   491         return
   491         return
   492     b2caps = bundle2.bundle2caps(pushop.remote)
   492     b2caps = bundle2.bundle2caps(pushop.remote)
   493     if not 'b2x:pushkey' in b2caps:
   493     if not 'pushkey' in b2caps:
   494         return
   494         return
   495     pushop.stepsdone.add('phases')
   495     pushop.stepsdone.add('phases')
   496     part2node = []
   496     part2node = []
   497     enc = pushkey.encode
   497     enc = pushkey.encode
   498     for newremotehead in pushop.outdatedphases:
   498     for newremotehead in pushop.outdatedphases:
   499         part = bundler.newpart('b2x:pushkey')
   499         part = bundler.newpart('pushkey')
   500         part.addparam('namespace', enc('phases'))
   500         part.addparam('namespace', enc('phases'))
   501         part.addparam('key', enc(newremotehead.hex()))
   501         part.addparam('key', enc(newremotehead.hex()))
   502         part.addparam('old', enc(str(phases.draft)))
   502         part.addparam('old', enc(str(phases.draft)))
   503         part.addparam('new', enc(str(phases.public)))
   503         part.addparam('new', enc(str(phases.public)))
   504         part2node.append((part.id, newremotehead))
   504         part2node.append((part.id, newremotehead))
   531 def _pushb2bookmarks(pushop, bundler):
   531 def _pushb2bookmarks(pushop, bundler):
   532     """handle phase push through bundle2"""
   532     """handle phase push through bundle2"""
   533     if 'bookmarks' in pushop.stepsdone:
   533     if 'bookmarks' in pushop.stepsdone:
   534         return
   534         return
   535     b2caps = bundle2.bundle2caps(pushop.remote)
   535     b2caps = bundle2.bundle2caps(pushop.remote)
   536     if 'b2x:pushkey' not in b2caps:
   536     if 'pushkey' not in b2caps:
   537         return
   537         return
   538     pushop.stepsdone.add('bookmarks')
   538     pushop.stepsdone.add('bookmarks')
   539     part2book = []
   539     part2book = []
   540     enc = pushkey.encode
   540     enc = pushkey.encode
   541     for book, old, new in pushop.outbookmarks:
   541     for book, old, new in pushop.outbookmarks:
   542         part = bundler.newpart('b2x:pushkey')
   542         part = bundler.newpart('pushkey')
   543         part.addparam('namespace', enc('bookmarks'))
   543         part.addparam('namespace', enc('bookmarks'))
   544         part.addparam('key', enc(book))
   544         part.addparam('key', enc(book))
   545         part.addparam('old', enc(old))
   545         part.addparam('old', enc(old))
   546         part.addparam('new', enc(new))
   546         part.addparam('new', enc(new))
   547         action = 'update'
   547         action = 'update'
   581                 and pushop.ui.configbool('experimental', 'bundle2.pushback'))
   581                 and pushop.ui.configbool('experimental', 'bundle2.pushback'))
   582 
   582 
   583     # create reply capability
   583     # create reply capability
   584     capsblob = bundle2.encodecaps(bundle2.getrepocaps(pushop.repo,
   584     capsblob = bundle2.encodecaps(bundle2.getrepocaps(pushop.repo,
   585                                                       allowpushback=pushback))
   585                                                       allowpushback=pushback))
   586     bundler.newpart('b2x:replycaps', data=capsblob)
   586     bundler.newpart('replycaps', data=capsblob)
   587     replyhandlers = []
   587     replyhandlers = []
   588     for partgenname in b2partsgenorder:
   588     for partgenname in b2partsgenorder:
   589         partgen = b2partsgenmapping[partgenname]
   589         partgen = b2partsgenmapping[partgenname]
   590         ret = partgen(pushop, bundler)
   590         ret = partgen(pushop, bundler)
   591         if callable(ret):
   591         if callable(ret):
   973     pullop.stepsdone.add('changegroup')
   973     pullop.stepsdone.add('changegroup')
   974 
   974 
   975     kwargs['common'] = pullop.common
   975     kwargs['common'] = pullop.common
   976     kwargs['heads'] = pullop.heads or pullop.rheads
   976     kwargs['heads'] = pullop.heads or pullop.rheads
   977     kwargs['cg'] = pullop.fetch
   977     kwargs['cg'] = pullop.fetch
   978     if 'b2x:listkeys' in remotecaps:
   978     if 'listkeys' in remotecaps:
   979         kwargs['listkeys'] = ['phase', 'bookmarks']
   979         kwargs['listkeys'] = ['phase', 'bookmarks']
   980     if not pullop.fetch:
   980     if not pullop.fetch:
   981         pullop.repo.ui.status(_("no changes found\n"))
   981         pullop.repo.ui.status(_("no changes found\n"))
   982         pullop.cgresult = 0
   982         pullop.cgresult = 0
   983     else:
   983     else:
  1126             pullop.repo.invalidatevolatilesets()
  1126             pullop.repo.invalidatevolatilesets()
  1127     return tr
  1127     return tr
  1128 
  1128 
  1129 def caps20to10(repo):
  1129 def caps20to10(repo):
  1130     """return a set with appropriate options to use bundle20 during getbundle"""
  1130     """return a set with appropriate options to use bundle20 during getbundle"""
  1131     caps = set(['HG2Y'])
  1131     caps = set(['HG20'])
  1132     capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
  1132     capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
  1133     caps.add('bundle2=' + urllib.quote(capsblob))
  1133     caps.add('bundle2=' + urllib.quote(capsblob))
  1134     return caps
  1134     return caps
  1135 
  1135 
  1136 # List of names of steps to perform for a bundle2 for getbundle, order matters.
  1136 # List of names of steps to perform for a bundle2 for getbundle, order matters.
  1159 
  1159 
  1160 def getbundle(repo, source, heads=None, common=None, bundlecaps=None,
  1160 def getbundle(repo, source, heads=None, common=None, bundlecaps=None,
  1161               **kwargs):
  1161               **kwargs):
  1162     """return a full bundle (with potentially multiple kind of parts)
  1162     """return a full bundle (with potentially multiple kind of parts)
  1163 
  1163 
  1164     Could be a bundle HG10 or a bundle HG2Y depending on bundlecaps
  1164     Could be a bundle HG10 or a bundle HG20 depending on bundlecaps
  1165     passed. For now, the bundle can contain only changegroup, but this will
  1165     passed. For now, the bundle can contain only changegroup, but this will
  1166     changes when more part type will be available for bundle2.
  1166     changes when more part type will be available for bundle2.
  1167 
  1167 
  1168     This is different from changegroup.getchangegroup that only returns an HG10
  1168     This is different from changegroup.getchangegroup that only returns an HG10
  1169     changegroup bundle. They may eventually get reunited in the future when we
  1169     changegroup bundle. They may eventually get reunited in the future when we
  1210     """add a changegroup part to the requested bundle"""
  1210     """add a changegroup part to the requested bundle"""
  1211     cg = None
  1211     cg = None
  1212     if kwargs.get('cg', True):
  1212     if kwargs.get('cg', True):
  1213         # build changegroup bundle here.
  1213         # build changegroup bundle here.
  1214         version = None
  1214         version = None
  1215         cgversions = b2caps.get('b2x:changegroup')
  1215         cgversions = b2caps.get('changegroup')
  1216         if not cgversions:  # 3.1 and 3.2 ship with an empty value
  1216         if not cgversions:  # 3.1 and 3.2 ship with an empty value
  1217             cg = changegroup.getchangegroupraw(repo, source, heads=heads,
  1217             cg = changegroup.getchangegroupraw(repo, source, heads=heads,
  1218                                                common=common,
  1218                                                common=common,
  1219                                                bundlecaps=bundlecaps)
  1219                                                bundlecaps=bundlecaps)
  1220         else:
  1220         else:
  1226                                                common=common,
  1226                                                common=common,
  1227                                                bundlecaps=bundlecaps,
  1227                                                bundlecaps=bundlecaps,
  1228                                                version=version)
  1228                                                version=version)
  1229 
  1229 
  1230     if cg:
  1230     if cg:
  1231         part = bundler.newpart('b2x:changegroup', data=cg)
  1231         part = bundler.newpart('changegroup', data=cg)
  1232         if version is not None:
  1232         if version is not None:
  1233             part.addparam('version', version)
  1233             part.addparam('version', version)
  1234 
  1234 
  1235 @getbundle2partsgenerator('listkeys')
  1235 @getbundle2partsgenerator('listkeys')
  1236 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
  1236 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
  1237                             b2caps=None, **kwargs):
  1237                             b2caps=None, **kwargs):
  1238     """add parts containing listkeys namespaces to the requested bundle"""
  1238     """add parts containing listkeys namespaces to the requested bundle"""
  1239     listkeys = kwargs.get('listkeys', ())
  1239     listkeys = kwargs.get('listkeys', ())
  1240     for namespace in listkeys:
  1240     for namespace in listkeys:
  1241         part = bundler.newpart('b2x:listkeys')
  1241         part = bundler.newpart('listkeys')
  1242         part.addparam('namespace', namespace)
  1242         part.addparam('namespace', namespace)
  1243         keys = repo.listkeys(namespace).items()
  1243         keys = repo.listkeys(namespace).items()
  1244         part.data = pushkey.encodekeys(keys)
  1244         part.data = pushkey.encodekeys(keys)
  1245 
  1245 
  1246 @getbundle2partsgenerator('obsmarkers')
  1246 @getbundle2partsgenerator('obsmarkers')
  1286         if util.safehasattr(cg, 'params'):
  1286         if util.safehasattr(cg, 'params'):
  1287             try:
  1287             try:
  1288                 tr = repo.transaction('unbundle')
  1288                 tr = repo.transaction('unbundle')
  1289                 tr.hookargs['source'] = source
  1289                 tr.hookargs['source'] = source
  1290                 tr.hookargs['url'] = url
  1290                 tr.hookargs['url'] = url
  1291                 tr.hookargs['bundle2-exp'] = '1'
  1291                 tr.hookargs['bundle2'] = '1'
  1292                 r = bundle2.processbundle(repo, cg, lambda: tr).reply
  1292                 r = bundle2.processbundle(repo, cg, lambda: tr).reply
  1293                 p = lambda: tr.writepending() and repo.root or ""
  1293                 p = lambda: tr.writepending() and repo.root or ""
  1294                 repo.hook('b2x-pretransactionclose', throw=True, pending=p,
  1294                 repo.hook('b2x-pretransactionclose', throw=True, pending=p,
  1295                           **tr.hookargs)
  1295                           **tr.hookargs)
  1296                 hookargs = dict(tr.hookargs)
  1296                 hookargs = dict(tr.hookargs)