def _pullbundle2(pullop): """pull data using bundle2 For now, the only supported data are changegroup.""" remotecaps = bundle2.bundle2caps(pullop.remote) kwargs = {'bundlecaps': caps20to10(pullop.repo)} # pulling changegroup pullop.stepsdone.add('changegroup') kwargs['common'] = pullop.common kwargs['heads'] = pullop.heads or pullop.rheads kwargs['cg'] = pullop.fetch if 'b2x:listkeys' in remotecaps: kwargs['listkeys'] = ['phase', 'bookmarks'] if not pullop.fetch: pullop.repo.ui.status(_("no changes found\n")) pullop.cgresult = 0 else: if pullop.heads is None and list(pullop.common) == [nullid]: pullop.repo.ui.status(_("requesting all changes\n")) if obsolete.isenabled(pullop.repo, obsolete.exchangeopt): remoteversions = bundle2.obsmarkersversion(remotecaps) if obsolete.commonversion(remoteversions) is not None: kwargs['obsmarkers'] = True pullop.stepsdone.add('obsmarkers') _pullbundle2extraprepare(pullop, kwargs) if kwargs.keys() == ['format']: return # nothing to pull bundle = pullop.remote.getbundle('pull', **kwargs) try: op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction) except error.BundleValueError, exc: raise util.Abort('missing support for %s' % exc)
def _pushb2phases(pushop, bundler): """handle phase push through bundle2""" if 'phases' in pushop.stepsdone: return b2caps = bundle2.bundle2caps(pushop.remote) if not 'b2x:pushkey' in b2caps: return pushop.stepsdone.add('phases') part2node = [] enc = pushkey.encode for newremotehead in pushop.outdatedphases: part = bundler.newpart('b2x:pushkey') part.addparam('namespace', enc('phases')) part.addparam('key', enc(newremotehead.hex())) part.addparam('old', enc(str(phases.draft))) part.addparam('new', enc(str(phases.public))) part2node.append((part.id, newremotehead)) def handlereply(op): for partid, node in part2node: partrep = op.records.getreplies(partid) results = partrep['pushkey'] assert len(results) <= 1 msg = None if not results: msg = _('server ignored update of %s to public!\n') % node elif not int(results[0]['return']): msg = _('updating %s to public failed!\n') % node if msg is not None: pushop.ui.warn(msg) return handlereply
def _pullbundle2(pullop): """pull data using bundle2 For now, the only supported data are changegroup.""" remotecaps = bundle2.bundle2caps(pullop.remote) kwargs = {'bundlecaps': caps20to10(pullop.repo)} # pulling changegroup pullop.todosteps.remove('changegroup') kwargs['common'] = pullop.common kwargs['heads'] = pullop.heads or pullop.rheads if 'b2x:listkeys' in remotecaps: kwargs['listkeys'] = ['phase'] if not pullop.fetch: pullop.repo.ui.status(_("no changes found\n")) pullop.cgresult = 0 else: if pullop.heads is None and list(pullop.common) == [nullid]: pullop.repo.ui.status(_("requesting all changes\n")) _pullbundle2extraprepare(pullop, kwargs) if kwargs.keys() == ['format']: return # nothing to pull bundle = pullop.remote.getbundle('pull', **kwargs) try: op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction) except error.BundleValueError, exc: raise util.Abort('missing support for %s' % exc)
def _pushbundle2(pushop): """push data to the remote using bundle2 The only currently supported type of data is changegroup but this will evolve in the future.""" bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote)) pushback = (pushop.trmanager and pushop.ui.configbool('experimental', 'bundle2.pushback')) # create reply capability capsblob = bundle2.encodecaps(bundle2.getrepocaps(pushop.repo, allowpushback=pushback)) bundler.newpart('b2x:replycaps', data=capsblob) replyhandlers = [] for partgenname in b2partsgenorder: partgen = b2partsgenmapping[partgenname] ret = partgen(pushop, bundler) if callable(ret): replyhandlers.append(ret) # do not push if nothing to push if bundler.nbparts <= 1: return stream = util.chunkbuffer(bundler.getchunks()) try: reply = pushop.remote.unbundle(stream, ['force'], 'push') except error.BundleValueError, exc: raise util.Abort('missing support for %s' % exc)
def _pushb2bookmarks(pushop, bundler): """handle phase push through bundle2""" if 'bookmarks' in pushop.stepsdone: return b2caps = bundle2.bundle2caps(pushop.remote) if 'b2x:pushkey' not in b2caps: return pushop.stepsdone.add('bookmarks') part2book = [] enc = pushkey.encode for book, old, new in pushop.outbookmarks: part = bundler.newpart('b2x:pushkey') part.addparam('namespace', enc('bookmarks')) part.addparam('key', enc(book)) part.addparam('old', enc(old)) part.addparam('new', enc(new)) action = 'update' if not old: action = 'export' elif not new: action = 'delete' part2book.append((part.id, book, action)) def handlereply(op): ui = pushop.ui for partid, book, action in part2book: partrep = op.records.getreplies(partid) results = partrep['pushkey'] assert len(results) <= 1 if not results: pushop.ui.warn(_('server ignored bookmark %s update\n') % book) else: ret = int(results[0]['return']) if ret: ui.status(bookmsgmap[action][0] % book) else: ui.warn(bookmsgmap[action][1] % book) if pushop.bkresult is not None: pushop.bkresult = 1 return handlereply
def _pushb2ctx(pushop, bundler): """handle changegroup push through bundle2 addchangegroup result is stored in the ``pushop.cgresult`` attribute. """ if 'changesets' in pushop.stepsdone: return pushop.stepsdone.add('changesets') # Send known heads to the server for race detection. if not _pushcheckoutgoing(pushop): return pushop.repo.prepushoutgoinghooks(pushop.repo, pushop.remote, pushop.outgoing) if not pushop.force: bundler.newpart('b2x:check:heads', data=iter(pushop.remoteheads)) b2caps = bundle2.bundle2caps(pushop.remote) version = None cgversions = b2caps.get('b2x:changegroup') if not cgversions: # 3.1 and 3.2 ship with an empty value cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push', pushop.outgoing) else: cgversions = [v for v in cgversions if v in changegroup.packermap] if not cgversions: raise ValueError(_('no common changegroup version')) version = max(cgversions) cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push', pushop.outgoing, version=version) cgpart = bundler.newpart('b2x:changegroup', data=cg) if version is not None: cgpart.addparam('version', version) def handlereply(op): """extract addchangegroup returns from server reply""" cgreplies = op.records.getreplies(cgpart.id) assert len(cgreplies['changegroup']) == 1 pushop.cgresult = cgreplies['changegroup'][0]['return'] return handlereply
def _pushbundle2(pushop): """push data to the remote using bundle2 The only currently supported type of data is changegroup but this will evolve in the future.""" bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote)) # create reply capability capsblob = bundle2.encodecaps(pushop.repo.bundle2caps) bundler.newpart('b2x:replycaps', data=capsblob) replyhandlers = [] for partgen in bundle2partsgenerators: ret = partgen(pushop, bundler) if callable(ret): replyhandlers.append(ret) # do not push if nothing to push if bundler.nbparts <= 1: return stream = util.chunkbuffer(bundler.getchunks()) try: reply = pushop.remote.unbundle(stream, ['force'], 'push') except error.BundleValueError, exc: raise util.Abort('missing support for %s' % exc)
def _pushsyncphase(pushop): """synchronise phase information locally and remotely""" unfi = pushop.repo.unfiltered() cheads = pushop.commonheads # even when we don't push, exchanging phase data is useful remotephases = pushop.remote.listkeys('phases') if (pushop.ui.configbool('ui', '_usedassubrepo', False) and remotephases # server supports phases and pushop.ret is None # nothing was pushed and remotephases.get('publishing', False)): # When: # - this is a subrepo push # - and remote support phase # - and no changeset was pushed # - and remote is publishing # We may be in issue 3871 case! # We drop the possible phase synchronisation done by # courtesy to publish changesets possibly locally draft # on the remote. remotephases = {'publishing': 'True'} if not remotephases: # old server or public only reply from non-publishing _localphasemove(pushop, cheads) # don't push any phase data as there is nothing to push else: ana = phases.analyzeremotephases(pushop.repo, cheads, remotephases) pheads, droots = ana ### Apply remote phase on local if remotephases.get('publishing', False): _localphasemove(pushop, cheads) else: # publish = False _localphasemove(pushop, pheads) _localphasemove(pushop, cheads, phases.draft) ### Apply local phase on remote # Get the list of all revs draft on remote by public here. # XXX Beware that revset break if droots is not strictly # XXX root we may want to ensure it is but it is costly outdated = unfi.set('heads((%ln::%ln) and public())', droots, cheads) b2caps = bundle2.bundle2caps(pushop.remote) if 'b2x:pushkey' in b2caps: # server supports bundle2, let's do a batched push through it # # This will eventually be unified with the changesets bundle2 push bundler = bundle2.bundle20(pushop.ui, b2caps) capsblob = bundle2.encodecaps(pushop.repo.bundle2caps) bundler.newpart('b2x:replycaps', data=capsblob) part2node = [] enc = pushkey.encode for newremotehead in outdated: part = bundler.newpart('b2x:pushkey') part.addparam('namespace', enc('phases')) part.addparam('key', enc(newremotehead.hex())) part.addparam('old', enc(str(phases.draft))) part.addparam('new', enc(str(phases.public))) part2node.append((part.id, newremotehead)) stream = util.chunkbuffer(bundler.getchunks()) try: reply = pushop.remote.unbundle(stream, ['force'], 'push') op = bundle2.processbundle(pushop.repo, reply) except error.BundleValueError, exc: raise util.Abort('missing support for %s' % exc) for partid, node in part2node: partrep = op.records.getreplies(partid) results = partrep['pushkey'] assert len(results) <= 1 msg = None if not results: msg = _('server ignored update of %s to public!\n') % node elif not int(results[0]['return']): msg = _('updating %s to public failed!\n') % node if msg is not None: pushop.ui.warn(msg) else: