def _capabilities(repo, proto): """return a list of capabilities for a repo This function exists to allow extensions to easily wrap capabilities computation - returns a lists: easy to alter - change done here will be propagated to both `capabilities` and `hello` command without any other action needed. """ # copy to prevent modification of the global list caps = list(wireprotocaps) if _allowstream(repo.ui): if repo.ui.configbool('server', 'preferuncompressed', False): caps.append('stream-preferred') requiredformats = repo.requirements & repo.supportedformats # if our local revlogs are just revlogv1, add 'stream' cap if not requiredformats - set(('revlogv1',)): caps.append('stream') # otherwise, add 'streamreqs' detailing our local revlog format else: caps.append('streamreqs=%s' % ','.join(requiredformats)) if repo.ui.configbool('experimental', 'bundle2-exp', False): capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo)) caps.append('bundle2-exp=' + urllib.quote(capsblob)) caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority)) caps.append('httpheader=1024') return caps
def _pullbundle2(pullop): """pull data using bundle2 For now, the only supported data are changegroup.""" kwargs = {'bundlecaps': set(['HG2X'])} capsblob = bundle2.encodecaps(pullop.repo.bundle2caps) kwargs['bundlecaps'].add('bundle2=' + urllib.quote(capsblob)) # pulling changegroup pullop.todosteps.remove('changegroup') kwargs['common'] = pullop.common kwargs['heads'] = pullop.heads or pullop.rheads 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 bundle2.UnknownPartError, 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 _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.""" # Send known head to the server for race detection. capsblob = urllib.unquote(pushop.remote.capable('bundle2-exp')) caps = bundle2.decodecaps(capsblob) bundler = bundle2.bundle20(pushop.ui, caps) # create reply capability capsblob = bundle2.encodecaps(pushop.repo.bundle2caps) bundler.addpart(bundle2.bundlepart('b2x:replycaps', data=capsblob)) if not pushop.force: part = bundle2.bundlepart('B2X:CHECK:HEADS', data=iter(pushop.remoteheads)) bundler.addpart(part) extrainfo = _pushbundle2extraparts(pushop, bundler) # add the changegroup bundle cg = changegroup.getlocalbundle(pushop.repo, 'push', pushop.outgoing) cgpart = bundle2.bundlepart('B2X:CHANGEGROUP', data=cg.getchunks()) bundler.addpart(cgpart) stream = util.chunkbuffer(bundler.getchunks()) try: reply = pushop.remote.unbundle(stream, ['force'], 'push') except bundle2.UnknownPartError, exc: raise util.Abort('missing support for %s' % exc)
def _capabilities(repo, proto): """return a list of capabilities for a repo This function exists to allow extensions to easily wrap capabilities computation - returns a lists: easy to alter - change done here will be propagated to both `capabilities` and `hello` command without any other action needed. """ # copy to prevent modification of the global list caps = list(wireprotocaps) if _allowstream(repo.ui): if repo.ui.configbool("server", "preferuncompressed", False): caps.append("stream-preferred") requiredformats = repo.requirements & repo.supportedformats # if our local revlogs are just revlogv1, add 'stream' cap if not requiredformats - set(("revlogv1",)): caps.append("stream") # otherwise, add 'streamreqs' detailing our local revlog format else: caps.append("streamreqs=%s" % ",".join(requiredformats)) if repo.ui.configbool("experimental", "bundle2-advertise", True): capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo)) caps.append("bundle2=" + urllib.quote(capsblob)) caps.append("unbundle=%s" % ",".join(changegroupmod.bundlepriority)) caps.append("httpheader=%d" % repo.ui.configint("server", "maxhttpheaderlen", 1024)) return caps
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 caps20to10(repo): """return a set with appropriate options to use bundle20 during getbundle""" caps = set(['HG2Y']) capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo)) caps.add('bundle2=' + urllib.quote(capsblob)) return caps
def caps20to10(repo): """return a set with appropriate options to use bundle20 during getbundle""" caps = set(['HG2X']) capsblob = bundle2.encodecaps(repo.bundle2caps) caps.add('bundle2=' + urllib.quote(capsblob)) return caps
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: