py3: make metadata values be byte strings as Mercurial expects
from__future__importabsolute_importimportcollectionsimportweakreffrommercurial.i18nimport_frommercurialimport(bundle2,discovery,error,exchange,extensions,util,)from.import(common,)try:frommercurialimportwireprotowireproto.branchmapexcept(AttributeError,ImportError):# <= hg-4.5frommercurialimportwireprotov1serveraswireprotodef_headssummary(orig,pushop,*args,**kwargs):# In mercurial > 4.3, we receive the pushop as argumentsrepo=pushop.repo.unfiltered()remote=pushop.remotepublishing=('phases'notinremote.listkeys('namespaces')orbool(remote.listkeys('phases').get('publishing',False)))ifnotcommon.hastopicext(pushop.repo):returnorig(pushop,*args,**kwargs)elif((publishingornotremote.capable('topics'))andnotgetattr(pushop,'publish',False)):returnorig(pushop,*args,**kwargs)publishedset=()remotebranchmap=Noneorigremotebranchmap=remote.branchmappublishednode=[c.node()forcinpushop.outdatedphases]publishedset=repo.revs('ancestors(%ln + %ln)',publishednode,pushop.remotephases.publicheads)rev=repo.unfiltered().changelog.nodemap.getdefremotebranchmap():# drop topic information from changeset about to be publishedresult=collections.defaultdict(list)forbranch,headsinorigremotebranchmap().iteritems():if':'notinbranch:result[branch].extend(heads)else:namedbranch=branch.split(':',1)[0]forhinheads:r=rev(h)ifrisnotNoneandrinpublishedset:result[namedbranch].append(h)else:result[branch].append(h)forheadsinresult.itervalues():heads.sort()returnresultclassrepocls(repo.__class__):# awful hack to see branch as "branch:topic"def__getitem__(self,key):ctx=super(repocls,self).__getitem__(key)oldbranch=ctx.branchrev=ctx.rev()defbranch():branch=oldbranch()ifrevinpublishedset:returnbranchtopic=ctx.topic()iftopic:branch="%s:%s"%(branch,topic)returnbranchctx.branch=branchreturnctxdefrevbranchcache(self):rbc=super(repocls,self).revbranchcache()localchangelog=self.changelogdefbranchinfo(rev,changelog=None):ifchangelogisNone:changelog=localchangelogbranch,close=changelog.branchinfo(rev)ifrevinpublishedset:returnbranch,closetopic=repo[rev].topic()iftopic:branch="%s:%s"%(branch,topic)returnbranch,closerbc.branchinfo=branchinforeturnrbcoldrepocls=repo.__class__try:repo.__class__=repoclsifremotebranchmapisnotNone:remote.branchmap=remotebranchmapunxx=repo.filtered('unfiltered-topic')repo.unfiltered=lambda:unxxpushop.repo=reposummary=orig(pushop)forkey,valueinsummary.iteritems():if':'inkey:# This is a topicifvalue[0]isNoneandvalue[1]:summary[key]=([value[1][0]],)+value[1:]returnsummaryfinally:if'unfiltered'invars(repo):delrepo.unfilteredrepo.__class__=oldrepoclsifremotebranchmapisnotNone:remote.branchmap=origremotebranchmapdefwireprotobranchmap(orig,repo,proto):ifnotcommon.hastopicext(repo):returnorig(repo,proto)oldrepo=repo.__class__try:classrepocls(repo.__class__):defbranchmap(self):usetopic=notself.publishing()returnsuper(repocls,self).branchmap(topic=usetopic)repo.__class__=repoclsreturnorig(repo,proto)finally:repo.__class__=oldrepo# Discovery have deficiency around phases, branch can get new heads with pure# phases change. This happened with a changeset was allowed to be pushed# because it had a topic, but it later become public and create a new branch# head.## Handle this by doing an extra check for new head creation server sidedef_nbheads(repo):data={}forbinrepo.branchmap().iterbranches():if':'inb[0]:continuedata[b[0]]=len(b[1])returndatadefhandlecheckheads(orig,op,inpart):"""This is used to check for new heads when publishing changeset"""orig(op,inpart)ifnotcommon.hastopicext(op.repo)orop.repo.publishing():returntr=op.gettransaction()iftr.hookargs['source']notin('push','serve'):# not a pushreturntr._prepushheads=_nbheads(op.repo)reporef=weakref.ref(op.repo)ifutil.safehasattr(tr,'validator'):# hg <= 4.7oldvalidator=tr.validatorelse:oldvalidator=tr._validatordefvalidator(tr):repo=reporef()ifrepoisnotNone:repo.invalidatecaches()finalheads=_nbheads(repo)forbranch,oldnbintr._prepushheads.iteritems():newnb=finalheads.pop(branch,0)ifoldnb<newnb:msg=_('push create a new head on branch "%s"'%branch)raiseerror.Abort(msg)forbranch,newnbinfinalheads.iteritems():if1<newnb:msg=_('push create more than 1 head on new branch "%s"'%branch)raiseerror.Abort(msg)returnoldvalidator(tr)ifutil.safehasattr(tr,'validator'):# hg <= 4.7tr.validator=validatorelse:tr._validator=validatorhandlecheckheads.params=frozenset()def_pushb2phases(orig,pushop,bundler):ifcommon.hastopicext(pushop.repo):checktypes=('check:heads','check:updated-heads')hascheck=any(p.typeinchecktypesforpinbundler._parts)ifnothascheckandpushop.outdatedphases:exchange._pushb2ctxcheckheads(pushop,bundler)returnorig(pushop,bundler)defwireprotocaps(orig,repo,proto):caps=orig(repo,proto)ifcommon.hastopicext(repo)andrepo.peer().capable('topics'):caps.append('topics')returncapsdefmodsetup(ui):"""run at uisetup time to install all destinations wrapping"""extensions.wrapfunction(discovery,'_headssummary',_headssummary)extensions.wrapfunction(wireproto,'branchmap',wireprotobranchmap)extensions.wrapfunction(wireproto,'_capabilities',wireprotocaps)# we need a proper wrap b2 part stuffextensions.wrapfunction(bundle2,'handlecheckheads',handlecheckheads)bundle2.handlecheckheads.params=frozenset()bundle2.parthandlermapping['check:heads']=bundle2.handlecheckheadsifutil.safehasattr(bundle2,'handlecheckupdatedheads'):# we still need a proper wrap b2 part stuffextensions.wrapfunction(bundle2,'handlecheckupdatedheads',handlecheckheads)bundle2.handlecheckupdatedheads.params=frozenset()bundle2.parthandlermapping['check:updated-heads']=bundle2.handlecheckupdatedheadsextensions.wrapfunction(exchange,'_pushb2phases',_pushb2phases)exchange.b2partsgenmapping['phase']=exchange._pushb2phases